~/qa-guides

~/qa-guides/black-box-vs-white-box-testing

>_ Black-Box vs White-Box Testing: Differences and Examples

Compare black-box and white-box testing through one shipping-rule example, including test design, branch coverage, common mistakes, and when to use each.

Test designBlack-box testingWhite-box testingCoverage

Published

Short answer

Black-box testing designs tests from specified behavior: give the software an input or action and compare the observable result with the requirement. White-box testing designs tests from internal structure: use code or a design model to select statements, branches, or other structural elements to exercise.

The difference is the basis for choosing tests. Both approaches can be useful for the same feature, and either can be used in an automated suite. A test that checks the right business result and a test that reaches a particular code branch answer different questions.

This guide compares black-box vs white-box testing through one shipping calculation. It explains how to select tests, what their coverage establishes, and why a suite can exercise every branch while missing an incorrect boundary condition.

What is black-box testing?

Black-box testing starts with what the software should do. Sources can include acceptance criteria, business rules, an interface contract, or an agreed behavior model. The test inputs and expected results come from those sources rather than from the implementation's current choices.

For example, if an agreed rule grants free shipping at a subtotal of 100 or more, the rule itself gives a reason to test exactly 100. You can select that test before reading the shipping function.

Useful black-box test design techniques include:

  • Equivalence partitioning: Group values expected to receive similar treatment, then choose representatives from the identified groups.
  • Boundary value analysis: Select values at and near the limits between ordered groups.
  • Decision table testing: Work through relevant combinations of conditions and their specified outcomes.
  • State transition testing: Select sequences of events from a model of states and permitted or forbidden transitions.

These techniques help explain why a particular scenario belongs in the suite. An arbitrary collection of example inputs may leave important rules or boundaries untested.

For endpoint-level scenarios, the API Test Cases Checklist provides practical request and expected-result examples. They can be designed from the API contract without inspecting its implementation.

What is white-box testing?

White-box testing starts with how the software is structured. A tester examines code or an internal model, identifies structural elements that need to be exercised, and chooses inputs or conditions that reach them.

For a shipping function with two decision outcomes, this can mean selecting one input that enters the free-shipping branch and another that enters the paid-shipping branch. The tester still needs an independent basis for deciding whether each returned amount is correct.

Two common measures are:

  • Statement coverage: The proportion of executable statements exercised by the tests.
  • Branch coverage: The proportion of control-flow branches exercised by the tests. In a simple conditional, the true and false outcomes are relevant branches.

The ISTQB Foundation Level syllabus, sections 4.1-4.3, distinguishes specification-based and structure-based techniques and describes these coverage measures. It also explains that full statement coverage does not necessarily exercise every branch, and full branch coverage does not establish that the software is defect-free.

Always name the coverage measure and its scope. A percentage for one function describes that function under the chosen measurement; it does not describe every requirement or the whole product.

Key differences between black-box and white-box testing

The practical differences affect test preparation, evidence, and maintenance:

  • Starting point: Black-box cases follow specified rules and observable outcomes. White-box cases follow the implementation or internal model's structure.
  • Information needed: Black-box design needs a usable behavioral expectation. White-box design also needs enough internal information to identify and target the structural elements being tested.
  • Coverage evidence: Black-box evidence can show which identified rules, partitions, boundaries, or transitions were tested. White-box evidence can show which selected internal elements were exercised.
  • Blind spots: A behavior-focused suite can miss unexercised internal logic. A structure-focused suite can exercise existing logic while missing an omitted rule or an incorrect expectation.
  • Maintenance trigger: A behavior change may alter the expected results of black-box cases. An internal refactor may require reviewing structural coverage even when the external behavior stays the same.

The categories describe test design, not ownership. A developer can derive a test from requirements, and a QA engineer can use internal structure to target an uncovered branch. Having access to source code does not automatically make every test white-box.

Worked example: one shipping rule, two test designs

This is an invented calculation for a two-decimal currency. It illustrates test selection rather than a complete store's shipping policy.

1. Define the required behavior

The simplified function accepts a valid, nonnegative integer subtotal in cents and returns a shipping amount in cents.

  • Below 100.00: Shipping costs 5.00.
  • At 100.00 or above: Shipping costs 0.00.
  • Representation: A subtotal of 100.00 is passed as 10000; a shipping charge of 5.00 is returned as 500.
  • Scope: There are no address, delivery-method, discount, tax, or membership conditions in this example. Invalid-input handling is outside this function's stated example scope.

Write these expectations before evaluating the implementation. They are the reference used to judge the results.

2. Derive black-box tests from the boundary

The inclusive free-shipping threshold gives three useful boundary cases:

  • BB-01: Call the calculation with 9999 cents, representing 99.99. Expect 500 cents in shipping.
  • BB-02: Call it with 10000 cents, representing exactly 100.00. Expect 0 cents in shipping.
  • BB-03: Call it with 10001 cents, representing 100.01. Expect 0 cents in shipping.

The test values come from the required boundary and the smallest input increment, one cent. No code inspection is needed to select them.

These three checks address this boundary. They do not establish coverage of every possible store workflow or input-validation rule.

3. Derive white-box tests from the implementation

Suppose the implementation has a defect. Its entire logic is one decision: if subtotalCents > 10000, return 0; otherwise return 500.

The comparison uses greater than, although the requirement includes equality. For this simplified model, select inputs that exercise both decision outcomes:

  • WB-01: Call with 8000 cents. The condition is false and the paid-shipping branch returns 500. The amount agrees with the requirement for 80.00.
  • WB-02: Call with 12000 cents. The condition is true and the free-shipping branch returns 0. The amount agrees with the requirement for 120.00.

Both tests pass and exercise both branches of this single-decision model. The model has 100% branch coverage, but neither input checks equality at the threshold.

Now run BB-02. The condition 10000 > 10000 is false, so the implementation returns 500. The required result is 0. The boundary test exposes the defect even though the two structural tests reached every branch.

This does not mean white-box testing cannot find boundary defects. A tester inspecting the comparison might choose the equality case immediately. It shows that meeting this particular coverage goal with these particular inputs was insufficient.

4. Combine the evidence and preserve the fix

The corrected comparison includes equality: subtotalCents >= 10000. Verify the change against the original rule and the selected structural elements:

  • BB-01 still returns 500 for 99.99.
  • BB-02 now returns 0 for exactly 100.00.
  • BB-03 still returns 0 for 100.01.
  • WB-01 and WB-02 still exercise the paid and free branches with correct amounts.

The behavioral checks establish the expected boundary results. The structural check establishes which branches were exercised. Keep both forms of evidence rather than treating the coverage percentage as the correctness assertion.

Add the boundary cases to the relevant regression testing checklist so later changes to this calculation preserve the agreed rule. Broader shipping functionality needs its own scenarios beyond this small example.

When should you use each approach?

Choose an approach by the question you need to answer and the information available. The examples below are starting points for test planning, not fixed assignments by role or test level.

Start with black-box design for specified behavior

Use behavior-based cases when you need evidence that a rule, acceptance criterion, or interface contract is satisfied.

For the shipping example, that means checking the agreed paid and free regions and their boundary. If the requirement later adds a second condition, identify its combinations and expected outcomes before assuming existing cases are sufficient.

This is also useful when implementation details are unavailable. Record unclear expectations as questions for the rule owner; observing the current output alone does not establish that it is correct.

Add white-box design for internal coverage gaps

Use structural information when you need to identify logic that the existing suite does not exercise. Examples include a newly added fallback branch, a decision outcome untouched by current tests, or an internal path affected by a refactor.

For each selected element, identify how to reach it and what observable result or state should follow. Distinguish code that was executed from behavior that was actually checked by an assertion.

Combine both when a change affects behavior and implementation

Review the requirement-derived cases first, then inspect whether the changed structure leaves important elements unexercised. Add cases that close a meaningful gap rather than adding tests only to increase a percentage.

In the shipping example, the boundary cases and branch cases may overlap in the code they exercise. A test does not need to be duplicated merely to carry a second label. Record the behavioral requirement it checks and any structural coverage it contributes.

How this relates to manual testing, automation, and test levels

Black-box and white-box describe how tests are derived. Manual and automated describe how testing activities are performed. Component, integration, system, and acceptance describe the scope or level of testing.

These dimensions can be combined. For example:

  • an automated component test can check the shipping rule using requirement-derived boundary values;
  • a manually executed request can check an observable API result against its contract;
  • a test designed to exercise a known internal branch can run through a function or a higher-level interface, if that interface can reach the branch.

In the worked example, BB-02 calls a function directly and is still selected from the specified behavior. Calling an API would not, by itself, change the basis of that test. Likewise, automating it would not turn it into a structure-derived case.

Practical checklist for choosing and combining tests

Before accepting the test design, check that:

  • the behavior being verified has an identifiable requirement or agreed rule;
  • expected results are written independently of the current implementation's output;
  • requirement-derived cases include relevant valid groups and their boundaries;
  • combinations or state changes are covered when the rule depends on them;
  • internal elements targeted by structural tests are named and reachable;
  • each structural test checks a meaningful result as well as executing code;
  • coverage reports name the metric, code scope, and exclusions;
  • uncovered requirements and uncovered internal elements are recorded separately;
  • overlapping tests are assessed for their contribution before adding duplicates;
  • tests that caught a defect are retained where they protect the affected behavior.

For the shipping example, the equality case and the true and false decision outcomes should all be visible in the review evidence. A green coverage report alone does not show those required results.

Common mistakes

1. Classifying tests by the tool that runs them

A browser, API client, or unit test runner does not determine the test design approach. Explain whether the case was selected from specified behavior or internal structure, and what evidence it produces.

2. Copying expected results from the implementation

If the current function charges shipping at exactly 100.00, copying that result into the test would preserve the example's defect. Check the expected amount against the agreed rule before accepting the test.

3. Treating 100% coverage as complete correctness

The two branch tests in the example exercise every branch while missing the incorrect comparison at equality. Coverage describes execution of selected elements; the assertions and chosen values still determine which failures can be detected.

4. Ignoring internal evidence after behavior checks pass

Passing boundary cases can leave an unrelated fallback or error branch untested in a real implementation. Review the relevant changed structure as well as the behavioral scenarios, and record remaining gaps.

5. Testing only the branches that already exist

A required condition might be absent from the implementation entirely. Tests selected only from existing structure may never ask about it. Keep the behavior model and requirements visible during review.

6. Assigning one approach exclusively to one role

A team can share requirements, code knowledge, and test evidence. Assign work according to the information and skills needed for the check rather than assuming a job title fixes how tests must be designed.

FAQ

Black-box test design derives cases from specified behavior and compares observable results with that expectation. White-box test design uses internal structure to select elements to exercise. The difference concerns test selection, so both can contribute evidence about the same feature.

No. The shipping boundary cases can be automated while remaining requirement-derived tests. Manual execution and automation are separate from the information used to choose a test. Likewise, a person can inspect internal logic to plan a structural test before deciding how to execute it.

No. Access makes structural information available, but the test's basis still matters. A case chosen because a requirement includes exactly 100.00 remains behavior-derived even when its author has read the code. A case chosen to reach a particular internal branch uses structural information.

The interface alone does not decide. A request chosen from a documented contract is a black-box example. A request chosen specifically to exercise a known internal branch uses a white-box basis. In either case, define an expected response or state independently of simply reaching the code.

Yes. In the single-decision shipping model, inputs of 80.00 and 120.00 exercise both branches and return correct amounts. They do not test exactly 100.00, where the incorrect greater-than comparison returns a charge instead of free shipping. The coverage claim is limited to that model and those branches.

Choose cases according to the changed behavior and internal impact. Requirement-derived cases protect agreed outcomes, while structural evidence can reveal changed logic that the suite does not exercise. Reassess both when needed; there is no universal ratio of black-box to white-box cases for every change.

Ready to turn this guide into a working QA project with statuses, comments, and CSV export?