ScreenshotNeo

BlogGuides

Software Testing Techniques: A Practical Guide

Learn how to choose and combine software testing techniques, with worked examples for inputs, business rules, states, code paths, and exploratory testing.

By the ScreenshotNeo team4 October 202613 min read

Software testing techniques help you turn requirements, code, and risk into a small, defensible set of test cases. Choose a technique based on what you know about the behavior, what could fail, and what coverage you need. Most useful test sets combine techniques: equivalence partitioning and boundary-value analysis for input ranges, decision tables for interacting rules, state-transition testing for workflows, white-box testing for code paths, and experience-based testing for risks the formal models miss.

The ISTQB Certified Tester Foundation Level (CTFL) syllabus v4.0 groups techniques into black-box, white-box, and experience-based families. These techniques guide test analysis (what to test) and test design (how to test); they do not replace clear requirements, sound risk judgment, or evaluation of test results. ISTQB CTFL v4.0 syllabus and materials.

1. What are software testing techniques?

A testing technique is a systematic way to derive test conditions, cases, or data from a test basis. The basis might be a requirement, business rule, state model, source code, architecture, or a tester’s knowledge of likely failure patterns.

Family Test basis Useful for Examples
Black-box (specification-based) Expected behavior and interfaces Checking behavior without relying on implementation details Equivalence partitioning, boundary-value analysis, decision tables, state transitions
White-box (structure-based) Internal code or control flow Checking statements, branches, and paths that behavior-only cases may not exercise Statement and branch testing
Experience-based Tester skill, defect history, and domain knowledge Probing risks that are hard to specify or model in advance Error guessing, exploratory testing, checklists
Collaboration-based Shared understanding of user stories and acceptance criteria Making expected behavior testable before implementation Collaborative story writing, acceptance test-driven development

Black-box cases can remain useful when implementation changes but required behavior stays the same. White-box cases depend more directly on structure. Experience-based work is skill-dependent and complements systematic methods; ISTQB notes that it can detect defects missed by black-box and white-box techniques.

2. How do I choose software testing techniques?

  1. State the risk or question. For example: “Can an out-of-range amount be accepted?” or “Can a locked account log in before recovery?”
  2. Identify the test basis. Find the requirement, interface contract, rule, state model, code, or product history that supports the test.
  3. Name the coverage item. Decide whether you need to cover partitions, boundaries, combinations, transitions, statements, or branches. A coverage percentage is meaningful only when its denominator is clear.
  4. Choose a technique that matches. Use partitions for classes of data, boundaries for ordered limits, tables for condition combinations, transitions for event sequences, code coverage for implementation structure, and exploration for uncertain behavior.
  5. Combine methods where risks differ. A test that covers a requirement may not traverse every code branch; branch coverage does not prove the requirement is right.
  6. Keep cases diagnostic. Separate unrelated invalid conditions where one failure could mask another. Record expected outcomes and relevant setup.
  7. Review maintenance cost. Keep models and cases aligned with current behavior; automate stable, repeatable checks and retain human exploration for changing or ambiguous areas.

Quick selection table

Question Good starting technique Coverage item
Which representative inputs should I sample? Equivalence partitioning Identified partitions
Are limits inclusive, exclusive, or shifted? Boundary-value analysis Boundary values and adjacent values
Do several conditions determine an outcome? Decision-table testing Rules or selected combinations
Does event order change what is allowed? State-transition testing States and transitions
Which parts of this implementation execute? Statement or branch testing Statements or branches
What might users or past defects expose? Exploratory testing, error guessing, checklists Charter objectives and recorded observations

3. Black-box techniques: test behavior from the specification

Black-box test design starts from specified behavior rather than internal code. You can apply it at different test levels, provided the test basis describes the expected behavior at that scope.

Equivalence partitioning: reduce redundant input sampling

Divide the input domain into non-empty, non-overlapping partitions whose values are expected to be treated alike. Include valid and invalid partitions when they have distinct expected behavior. Select at least one representative from each identified partition; split a partition further when values inside it do not actually behave alike. When testing invalid partitions, exercise them individually if simultaneous invalid conditions could hide one another.

Worked example: a form accepts an integer quantity from 1 through 10 inclusive. A first partition model is: integer below 1 (invalid), integer 1–10 (valid), integer above 10 (invalid), and non-integer or malformed input (invalid if the interface accepts raw text and specifies rejection). The exact partitions depend on the contract: a typed integer API and a text form may have different input classes.

Partition Example Expected result
Below range 0 Reject with the specified validation response
In range 6 Accept
Above range 11 Reject with the specified validation response
Malformed (if in scope) “six” Reject or report a type error, as specified

Do not claim “100% testing” from this sample. At most, it establishes coverage of the partitions you identified. A flawed partition model leaves behavior untested.

Boundary-value analysis: concentrate on edges

Boundary-value analysis applies to ordered partitions. Many limit defects involve a boundary being shifted or omitted. State whether the endpoints are inclusive and whether you use a two-value or three-value method.

For the inclusive integer range 1–10, a three-value boundary set around each edge is 0, 1, 2 and 9, 10, 11: just below, at, and just above each boundary. If test cost is constrained, a two-value method may use the boundary and its nearest outside neighbor (0, 1 and 10, 11), but it samples fewer adjacent values. For non-integer domains, choose valid adjacent values according to the domain’s precision; for timestamps, consider timezone and precision rules. Do not assume an arbitrary “just below” value where the domain has no defined increment.

Decision tables: test combinations of conditions

Use a decision table when combinations of conditions determine actions, especially for business rules. List meaningful conditions and outcomes, create columns for rules or combinations, and select cases that cover each relevant rule. Identify impossible combinations, defaults, and precedence explicitly; reduce combinations only when the rules justify it.

Checkout example:

Rule Account active? Payment valid? Item in stock? Expected outcome
1 Yes Yes Yes Place order
2 No Yes Yes Require account reactivation
3 Yes No Yes Reject payment
4 Yes Yes No Report unavailable item
5 No No No Apply documented precedence or report all applicable errors

The fifth row is a prompt to clarify the specification, not an invented product rule. If the expected outcome is undefined, raise the ambiguity rather than encoding a guess as a test oracle.

State-transition testing: exercise events and sequences

Model states, events, optional guards, and actions. Derive cases for valid transitions and relevant invalid transitions. A screen-by-screen check can miss sequence-dependent defects, such as an old session becoming usable after a password reset.

Account lockout example: states are Active and Locked. A failed login increments the failure count; reaching the documented threshold transitions to Locked. A successful login in Active grants access. A recovery event may return Locked to Active after a required verification step. Test sequences that reach the threshold, one attempt below it, another attempt while locked, recovery with valid and invalid verification, and login after recovery. The threshold and recovery rules must come from the product specification.

State tables make the model reviewable: current state + event + guard → next state + action. Include invalid-event behavior where it matters, such as a recovery event for an already active account. Track transition coverage separately from state coverage: visiting each state does not show that each relevant transition was exercised.

4. White-box techniques: test the code structure

White-box design uses internal structure or control flow. CTFL v4.0 highlights statement and branch testing. A branch is a transfer of control between nodes in a control-flow graph, conditional or unconditional. Structural coverage can reveal unvisited implementation logic, especially where the specification is incomplete, but it cannot show by itself that the implementation matches user needs.

def can_withdraw(balance, amount):
    if amount > 0 and amount <= balance:
        return True
    return False

# Example checks for outcomes and decisions:
assert can_withdraw(100, 50) is True   # valid withdrawal
assert can_withdraw(100, 0) is False   # non-positive amount
assert can_withdraw(100, 101) is False # amount exceeds balance

The example exercises the true and false outcomes of the outer decision. For a detailed branch-coverage claim, inspect the actual control-flow graph and language evaluation behavior: the compound condition may contain short-circuit evaluation that creates additional decision outcomes in some coverage tools. Statement coverage asks whether each executable statement ran; branch coverage asks whether each branch outcome ran. Neither measure proves that assertions are correct, all relevant inputs are represented, or the requirements are complete.

Use coverage reports to find gaps and guide additional cases, not as a standalone quality score. Exclusions, generated code, defensive branches, and infeasible paths need explicit treatment in the team’s coverage policy.

5. Experience-based techniques: use tester knowledge deliberately

Error guessing

Turn domain knowledge and defect history into focused probes. For a login form, useful guesses might include leading/trailing spaces, repeated submission, expired reset links, case handling, stale sessions, and a locked account with an active session. Tie each guess to a risk and expected observation; do not treat a long list of guesses as a substitute for requirements-based coverage.

Exploratory testing

Exploratory testing combines learning, test design, execution, and evaluation: what the tester learns shapes the next action. A short charter makes the work reproducible.

  1. Charter: Explore account recovery after lockout, focusing on stale links and session behavior.
  2. Timebox: Set a session length appropriate to the risk and record it.
  3. Observe: Record environment, test data, steps, actual result, and unexpected behavior.
  4. Follow up: Turn confirmed defects into reproducible cases; add durable checks for stable, high-risk behavior.

Checklist-based testing

Use a concise, maintained checklist to apply known risk prompts consistently. For a checkout flow, prompts might cover duplicate submission, currency and rounding, inventory changes between view and purchase, expired authentication, and recovery from payment failure. Checklists should remind testers what to consider while leaving room to investigate new evidence.

6. Collaboration-based approaches: make behavior testable earlier

When requirements are still being created, collaborate on user stories and acceptance criteria. Acceptance test-driven development (ATDD) uses examples and acceptance tests to clarify expected behavior before implementation. This improves the test basis for later black-box design; it does not eliminate the need for integration, structural, risk-based, or exploratory testing. Ask what happens for valid, invalid, boundary, conflicting, and missing information before the rules become code.

7. Put techniques into test levels and types

Test levels describe scope; test types describe a quality characteristic or approach. CTFL v4.0 lists component, component-integration, system, system-integration, and acceptance test levels. It addresses functional, non-functional, black-box, and white-box testing as types or approaches; most types can be used at different levels.

Level Typical scope Technique examples
Component Individual unit or component Partitions, boundaries, statement and branch checks
Component integration Interfaces between components Decision tables for interface rules; error and sequence checks
System Complete integrated product State transitions, functional rules, non-functional testing, exploration
System integration System interfaces with other systems Contract partitions, failure sequences, timeout and recovery checks
Acceptance Readiness against user or business needs Acceptance examples, end-to-end scenarios, usability and workflow checks

These are examples, not exclusive assignments. A boundary check can exist at multiple levels if the corresponding interface or behavior has a meaningful boundary.

Confirmation and regression after a change

After a defect fix or enhancement, confirmation testing checks whether the specific fix works. Regression testing checks whether the change adversely affected other areas. ISTQB recommends both after changes. As practical guidance, select regression scope from risk, changed code, dependency impact, and past failure patterns; there is no universal fixed set of regression cases.

8. A repeatable workflow for designing a small, defensible suite

  1. Collect the basis: requirements, acceptance criteria, interface contracts, state diagrams, code, logs, and relevant defect history.
  2. List risks: user harm, financial impact, security or privacy exposure, data loss, availability, and likely change hotspots.
  3. Choose coverage targets: state explicitly what counts as a partition, boundary, rule, transition, statement, or branch.
  4. Derive cases: use one or more techniques matched to each risk. Record input, preconditions, action, expected result, and cleanup.
  5. Check for blind spots: look for omitted invalid classes, endpoints, rule combinations, transitions, implementation branches, and exploratory questions.
  6. Prioritize and automate: favor repeatable checks for stable high-risk behavior; retain human judgment where behavior is uncertain or visual context matters.
  7. Review evidence: record what ran, what passed or failed, environment and data, unresolved ambiguities, and residual risk.

9. Browser-based visual checks as a supporting testing method

For web products, screenshots can support visual regression, layout checks, responsive behavior, and review of rendered states. They are evidence for visual behavior, not a replacement for assertions about business rules, accessibility, application state, or backend effects. Make captures reproducible by controlling viewport, device scale, color scheme, locale, test data, fonts, animations, and wait condition. Compare like with like and investigate differences instead of assuming every pixel change is a defect.

DIY browser capture in Python with Playwright (install with pip install playwright and playwright install chromium):

import asyncio
from pathlib import Path
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page(viewport={"width": 1440, "height": 1000}, device_scale_factor=1)
        await page.goto("https://example.com", wait_until="networkidle", timeout=30000)
        await page.screenshot(path="page.png", full_page=True, animations="disabled")
        await browser.close()

asyncio.run(main())

Replace the example URL with your own page. In a real test, use a stable local or staging target and deterministic fixture data. Playwright documents screenshot options, including full-page captures and element screenshots, in its Python screenshot guide. Its navigation wait states have different meanings; “network idle” is not always suitable for pages with persistent connections, so use a specific selector or application-ready signal when possible.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. A GET request returns an image or PDF, and its options include full-page and element captures, viewport and device presets, waits, custom CSS, and more. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners, popups, and chat widgets are removed before the shot.
  • Bot checks, blank pages, and failed loads are never billed; response headers identify the page verdict and billing status.
  • An MCP server lets AI agents use screenshot, page-info, and PDF-capture tools.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000.

Sign up for 1,000 free screenshots a month, with no card required.

10. Performance, reliability, and cost considerations

  • Test design cost: More cases are not automatically better. A clear risk model and coverage target help avoid redundant samples while preserving important distinctions.
  • Execution time: Unit-level checks are often easier to run frequently; broad end-to-end scenarios can require more setup and be sensitive to environment and data. Measure your own suite before setting budgets.
  • Reliability: Control clocks, network dependencies, random data, external services, browser versions, and asynchronous waits. Prefer explicit readiness conditions over arbitrary sleeps where possible.
  • Maintenance: Update tests when intended behavior changes. Retire obsolete cases and investigate flaky ones rather than rerunning until green.
  • Coverage interpretation: Report the denominator and exclusions. Coverage is evidence of exercised items, not proof of correctness or user value.
  • Screenshot API cost: ScreenshotNeo bills only clean shots; bot checks, CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Plans listed for the product are Free (1,000/month), Starter $5 (3,000), Growth $15 (15,000), Pro $39 (60,000), Scale $99 (250,000), and Business $249 (1,000,000); yearly billing gives two months free, and every feature is on every plan. Check the product site for current details before choosing.

11. Troubleshooting common test-design problems

Symptom Likely cause Fix
Many test cases exercise the same behavior Partitions overlap or are too granular without distinct outcomes Define expected treatment first; merge equivalent values and keep separate classes where behavior differs.
A boundary test fails unexpectedly Inclusive/exclusive endpoint, precision, timezone, or rounding rule is unclear Clarify the contract and record the exact domain increment and endpoint convention.
One invalid input hides another defect Several invalid conditions were combined into one case Test invalid partitions individually when the visible failure could mask other results.
Decision-table cases contradict each other Rules overlap, precedence is unspecified, or impossible combinations were included Review the table with a domain owner and specify precedence/default behavior.
State coverage is high but workflow defects remain Tests visit states without exercising transitions or event sequences Measure relevant transition coverage and test sequences, guards, and invalid events.
Statement coverage is high but a condition is wrong Statements ran, but decision outcomes or expected results were not adequately checked Add branch-oriented cases and assertions derived from requirements.
Exploratory findings cannot be reproduced Environment, data, actions, or observations were not recorded Capture steps, state, inputs, browser and environment details, and a minimal reproduction.
Browser screenshot tests are flaky Dynamic content, animations, fonts, viewport, or readiness varies Fix test data and viewport, disable animation where appropriate, and wait for a meaningful ready condition.
Screenshot API call returns an unexpected result URL, access key, wait condition, or target response is wrong Check request parameters and response headers, inspect the page verdict, and consult the API docs.

12. Frequently asked questions

Which testing technique is best?

There is no universal best technique. Match the method to the test basis, risk, required coverage item, and available information; combine methods where they address different failure modes.

Are black-box and functional testing the same?

No. Black-box describes a test-design perspective that does not depend on internal structure. Functional testing checks specified functions. A functional test can be designed using black-box techniques, while other test types can also use black-box methods.

Does 100% branch coverage mean the software is correct?

No. It means the measured branches were exercised under the tool’s definition. It does not prove requirements are complete, expected results are correct, or all relevant inputs and quality risks were tested.

Should I automate every test case?

Automate stable, repeatable checks when the maintenance and execution tradeoff makes sense. Human exploration remains useful for ambiguous behavior, new risks, and observations that are difficult to encode as assertions.

What is the difference between confirmation and regression testing?

Confirmation testing checks that a particular change fixes the reported issue. Regression testing checks whether that change harmed other behavior.

Reference: Definitions and technique families in this guide follow the ISTQB CTFL v4.0 syllabus (2023); detailed black-box technique material is available in the ASTQB CTFL black-box techniques section, and the syllabus is available from the ISTQB CTFL v4.0 page.