A product does not appear as one solid block. Developers write functions, join functions into components, components call one another, several services join into a system, and eventually that system reaches users or operations.

Testing a fee-calculating function and testing an entire money-transfer flow obviously cannot be done in exactly the same way. The object is different, the bugs we want are different and the environment is different. That is where test levels come from.

What is a test level?

A test level is a group of test activities organised and managed together. Each level is associated with a particular version of the test object, from a small piece of code to the whole system in its usage context.

CTFL 4.0.1 uses five levels:

  1. Component testing
  2. Component integration testing
  3. System testing
  4. System integration testing
  5. Acceptance testing

The old version of this article combined the two integration levels as Integration Test, which is still common project language. I am separating them this time so two people do not both say “integration” while one is testing between two classes and the other is testing between a banking app and a payment gateway.

V-Model illustrating the relationship between development and test activities
V-Model illustrating the relationship between development and test activities

The V-Model is an easy way to see how test levels relate to corresponding work products. It does not mean every project must finish one branch before any testing can happen.

Component testing

Component testing, often simply called unit testing, checks a component in a relatively isolated state. A component may be a function, class, module or a larger unit, depending on the architecture.

Suppose we have a fee function:

def fee(amount):
    if amount <= 0:
        raise ValueError("amount must be positive")
    return amount * 0.01

At this level we care about things such as:

Developers usually own this work because they are closest to the code and can fix it immediately. Testers may contribute when the team needs testing skills or has component tests at a higher level. The important thing is not stamping this “developer work” or “tester work”; the component needs a fence before it is joined to anything else.

Typical question: Who is responsible for component testing?

Developers usually own most component tests because they work closest to the code. Testers may also contribute depending on the product, skills and required independence.

Component integration testing

Two components working perfectly on their own does not tell us that they will work when they call each other.

Component A sends amount as a decimal while component B parses an integer. A service times out after 10 seconds while the client gives up at three. The sender calls the field userId while the receiver waits for customer_id. This is component integration testing territory.

Common failures include:

Developers can test with unit/component tests using fakes, stubs or test containers. Testers can test an API or an integrated build. Whether there is a frontend is not the boundary that decides who may do the work.

Big bang and incremental

Big bang joins many parts and then tests once. The initial setup may look easier, but when a failure appears, narrowing down the culprit is miserable.

Incremental integration joins pieces gradually. If a dependency is not ready, the team can use:

Teams integrate continuously these days, but CI does not automatically mean good integration testing. A green pipeline proves only that the tests that were written are green.

System testing

System testing checks the behaviour and quality characteristics of a relatively complete system. The test basis may include requirements, user stories, use cases, risks, specifications and rules agreed by the team.

Here we see flows such as:

An independent test team often performs most system testing because the viewpoint outside the implementation is valuable. But “only testers perform System Testing” is too strong. Developers, specialists or another team may contribute; the context and required independence decide.

Typical question: What is system testing?

System testing verifies the behaviour and quality characteristics of a complete system against its test basis in an environment representative of its intended use.

System integration testing

System integration testing checks the interface between the system under test and another system or external service.

Take an e-commerce app calling a payment gateway:

This is often grouped under integration testing or system testing, which is perfectly normal. As scope grows, the separate name helps the team say whether it is testing inside one system or the connection between several.

Acceptance testing

Acceptance testing assesses whether the system is ready to be accepted, deployed or used. It focuses on business needs, operational processes, contractual obligations or regulations, depending on the context.

Participants may be end users, customers, Product Owners, business representatives, operations teams or an authority. Testers often support the environment, data and scenarios and record issues. The decision to accept belongs to the authorised party, not automatically to the tester.

Common forms include:

FormFocus
User acceptance testingCan users or the business complete real work?
Operational acceptance testingAre backup, restore, monitoring, operations and support ready?
Contractual acceptance testingDoes the product meet the contract's acceptance criteria?
Regulatory acceptance testingDoes the product meet relevant regulations?
Alpha/Beta testingGather feedback from users in a controlled or real-world environment.

UAT is not a customer clicking a few things and signing because the deadline has arrived. If acceptance criteria are vague or the environment does not resemble real operation, the signature only closes paperwork; it does not reduce system risk.

Do we always go from low to high?

In terms of dependency, a component must exist before it can be joined into a system. But test activities do not have to queue in absolute order.

While developers write component tests, testers can review acceptance criteria, design system tests, prepare data and work on contracts. Some levels run in parallel or repeat for each increment. Do not look at the V-Model and turn it into a concrete waterfall.

Closing

LevelShort question
ComponentDoes this isolated part run correctly?
Component integrationDo the joined code parts follow their contract?
SystemDoes the whole system meet the test basis?
System integrationDoes the system communicate correctly with other systems?
AcceptanceIs the product ready for the authorised party to accept?

Knowing the level helps identify the test object, objective, environment and people who need to participate. The next article is Test Plan: before testing all these things, the team has to agree on scope, resources, risks and stop conditions.

References