Software Engineering Principles

Chapter 8
Verification, Validation and Software Quality

Bachelors Program in Full Stack Development
Software Engineering Principles   •   Bachelor

Verification, Validation and Software Quality

Introduction

Software quality is not achieved by testing at the end of development. It is created through disciplined requirements engineering, design, implementation, review, measurement, testing, release control, and continuous improvement. Verification and validation (V&V) provide the intellectual and practical foundation for this discipline.

Verification asks whether the product is being built correctly according to specified requirements, design decisions, coding standards, and process expectations. Validation asks whether the resulting product solves the users’ real problem and is fit for its intended use. A system may be verified yet fail validation: it may implement the documented requirements accurately while the requirements themselves are incomplete or unsuitable.

For full-stack developers, quality includes client-side behavior, server-side logic, APIs, databases, security controls, deployment configuration, accessibility, performance, and operational maintainability. Consequently, testing must be risk-based and layered rather than limited to checking individual functions.

Learning Objectives

By the end of this chapter, students should be able to:

  • distinguish verification from validation and quality assurance from quality control;
  • design a risk-based test strategy for a full-stack application;
  • explain unit, integration, system, acceptance, regression, performance, and usability testing;
  • select suitable test automation and coverage measures;
  • conduct reviews and manage defects systematically;
  • apply software quality models and meaningful quality metrics;
  • evaluate quality risks, ethical responsibilities, and limitations of testing.

1. Foundations of Software Quality

1.1 Quality as conformance and fitness

Two complementary views of quality are useful:

  1. Conformance to requirements: the product satisfies explicit functional and non-functional specifications.
  2. Fitness for use: the product is useful, reliable, secure, understandable, accessible, and satisfactory in its real context.

Quality is therefore multidimensional. A payment service that produces correct totals but exposes card details is not high quality. A highly secure application that users cannot understand may also fail its purpose.

A practical quality model commonly considers:

Quality characteristicTypical question
Functional suitabilityDoes the system provide the required functions accurately and completely?
Performance efficiencyDoes it respond within acceptable time and resource limits?
CompatibilityCan it coexist and interoperate with other systems?
UsabilityCan intended users learn and operate it effectively?
ReliabilityDoes it perform consistently under stated conditions?
SecurityDoes it protect confidentiality, integrity, authenticity, and availability?
MaintainabilityCan the system be analyzed, modified, and tested economically?
PortabilityCan it be transferred to another environment?
AccessibilityCan people with diverse abilities use it?

These characteristics are related but not interchangeable. Increasing security controls may affect usability; optimizing speed may reduce maintainability; adding redundancy may increase cost and complexity.

1.2 V&V, quality assurance, and quality control

Verification includes reviews, inspections, static analysis, traceability checks, and tests that compare an artifact with a specification. Validation includes demonstrations, user acceptance tests, usability studies, pilot releases, and operational evaluation.

Quality assurance (QA) is process-oriented. It establishes standards, prevents defects, audits practices, and improves the development process. Quality control (QC) is product-oriented. It identifies defects in a specific product through testing, inspection, and measurement. Testing is an important QC activity, but QA also asks why defects are being introduced and how the process can prevent recurrence.

The V-model illustrates a useful relationship: requirements correspond to acceptance testing, system design to system testing, architectural design to integration testing, and detailed design to unit testing. In agile development, these activities are not postponed to separate phases; they occur continuously through a “whole-team quality” approach.

2. A Risk-Based Test Strategy

A test strategy explains what will be tested, how it will be tested, when testing will occur, who will perform it, and what evidence is required. A risk-based strategy prioritizes effort according to the probability and impact of failure.

A simple qualitative risk model is:

Risk exposure = Probability of failure × Impact of failure

Probability is commonly rated from very low to very high, while impact may consider financial loss, safety, legal consequences, security exposure, reputation, and user harm. The multiplication is a prioritization aid, not a precise prediction. Its usefulness depends on consistent rating criteria.

For example, a defect in a rarely used administrative report may have moderate probability and low impact. An error in tax calculation may have moderate probability but very high financial and legal impact, so it deserves earlier and deeper testing.

A risk register should record:

  • risk statement and affected feature;
  • cause, event, and consequence;
  • likelihood and impact assessment;
  • controls and planned tests;
  • owner and target date;
  • residual risk after mitigation.

A good strategy also defines entry and exit criteria. Entry criteria might require testable builds, stable environments, and approved test data. Exit criteria might require that all critical tests pass, no unresolved critical defects remain, and residual risks have been accepted by an authorized stakeholder.

2.1 Test levels

#### Unit testing

Unit tests examine the smallest practical testable component, such as a function, class, React component, or validation rule. They should be fast, deterministic, isolated, and numerous enough to protect important logic. External databases, clocks, networks, and payment providers are often replaced with controlled test doubles.

Unit tests are particularly valuable for boundary conditions, invalid inputs, error handling, and business rules. They do not prove that components communicate correctly or that the complete application meets user needs.

#### Integration testing

Integration tests examine interactions between components. Examples include a service communicating with a database, a frontend consuming an API, or an authentication service issuing tokens. Integration tests reveal interface mismatches, serialization errors, transaction problems, incorrect configuration, and differences between mocked and real dependencies.

A useful distinction is between component integration, in which a limited set of components is tested together, and system integration, in which several subsystems or external services interact.

#### System testing

System testing evaluates the complete integrated application against functional and non-functional requirements. It may include account creation, search, checkout, authorization, error recovery, logging, and deployment behavior. System tests should be conducted in an environment sufficiently similar to production to expose configuration and infrastructure problems.

#### Acceptance testing

Acceptance testing determines whether the product is acceptable to its customer, product owner, regulator, or operational users. Acceptance criteria should be observable and measurable. A statement such as “the page should be fast” is weak; “the search results should appear within two seconds for the agreed workload” is testable.

User acceptance testing is not simply another technical test. It evaluates business fitness and may identify missing or misunderstood requirements.

#### Regression testing

Regression testing checks that changes have not damaged previously working behavior. A regression suite should be risk-prioritized rather than blindly expanded. It normally includes high-value business journeys, previously defective areas, stable API contracts, security-critical functions, and frequently changed components.

Continuous integration makes regression testing practical by running automated checks whenever code changes. Failed tests should provide actionable diagnostic information rather than merely reporting a red status.

2.2 Specialized testing

Performance testing examines responsiveness, throughput, resource use, and stability. Important types include:

  • load testing under expected demand;
  • stress testing beyond expected demand;
  • spike testing for abrupt demand changes;
  • endurance testing over an extended period;
  • scalability testing as users or data increase.

Performance requirements must specify workload, environment, and acceptance thresholds. A response-time result is meaningless without knowing request volume, data size, network conditions, and percentile. The 95th percentile response time means that 95% of measured responses are no slower than that value; it does not mean the average response time.

Usability testing observes representative users performing realistic tasks. It can reveal confusing navigation, unclear error messages, poor information hierarchy, and mismatches between the designer’s assumptions and users’ mental models. Accessibility testing should include keyboard operation, semantic structure, color contrast, screen-reader behavior, focus management, captions, and suitable automated and manual checks.

Security testing includes threat modeling, authorization tests, input validation, dependency scanning, secrets detection, penetration testing, and abuse-case analysis. Security must not be treated as a final test phase because insecure architecture may be expensive or impossible to repair late.

3. Test Design and Coverage

A test case should identify preconditions, inputs, actions, expected results, and postconditions. Effective test design does not require testing every possible input. It selects representative and high-risk cases systematically.

3.1 Common test design techniques

  • Equivalence partitioning: divide inputs into classes expected to behave similarly and test representatives from each class.
  • Boundary-value analysis: test values at, just below, and just above limits because defects often occur at boundaries.
  • Decision-table testing: represent combinations of conditions and resulting actions, particularly for business rules.
  • State-transition testing: test permitted and forbidden transitions, such as an order moving from pending to paid, shipped, and delivered.
  • Pairwise testing: cover combinations of parameter values efficiently when exhaustive combinations are impractical.
  • Property-based testing: generate many inputs and check general properties, such as serialization followed by deserialization preserving meaning.
  • Exploratory testing: learn, design, and execute tests simultaneously, guided by risk and observation.

3.2 Coverage measures

Coverage is evidence about what has been exercised, not proof that the software is correct. Common measures include statement coverage, branch coverage, condition coverage, path coverage, requirements coverage, and mutation score.

A basic statement coverage measure is:

Statement coverage (%) = (Executed statements ÷ Total statements) × 100

The formula assumes that statements are identified consistently and that the test run is representative. It does not measure the quality of assertions. A test can execute a line without checking whether the result is correct.

Branch coverage is often more informative for decisions because it asks whether each possible branch outcome has been executed. Even complete branch coverage cannot demonstrate that all combinations of conditions, timing effects, security threats, or user goals have been addressed.

Mutation testing deliberately introduces small changes, called mutants, into the code. A test suite that detects a mutant “kills” it. Mutation score can be expressed as:

Mutation score (%) = (Killed mutants ÷ Non-equivalent mutants) × 100

Equivalent mutants cannot be distinguished from the original program by any relevant test and should be excluded. Mutation testing can be computationally expensive, so it is most useful for critical modules and assessing the strength of assertions.

4. Automation and Continuous Quality

Automation is valuable when a test is repeatable, stable, frequently executed, and cheaper to automate than to perform manually. Unit and API tests are usually good automation candidates. Exploratory usability evaluation, ambiguous visual judgment, and some accessibility assessments still require human participation.

A sustainable automated test suite has:

  • clear naming and purposeful assertions;
  • isolated and reproducible data;
  • controlled clocks, randomness, and external services;
  • independent tests that can run in parallel where appropriate;
  • failure diagnostics, logs, screenshots, or traces;
  • version control and review;
  • maintenance ownership.

The “test pyramid” recommends many fast unit tests, fewer integration tests, and a smaller number of broad end-to-end tests. The exact shape depends on the system, but the principle is important: relying entirely on slow end-to-end tests produces feedback delays and fragile failures.

A continuous integration pipeline may perform the following sequence:

  1. compile and lint the code;
  2. run unit tests and static analysis;
  3. build deployable artifacts;
  4. run integration and contract tests;
  5. scan dependencies and secrets;
  6. deploy to a test environment;
  7. run selected system, performance, and acceptance checks;
  8. publish evidence and enforce quality gates.

Automation should not become a mechanism for hiding failures. Flaky tests—tests that pass and fail without a relevant product change—must be investigated, quarantined only temporarily, and assigned an owner. Ignoring flaky tests teaches the organization to distrust its feedback system.

5. Reviews and Defect Management

Testing executes software; reviews examine artifacts without executing them. Peer review, walkthroughs, inspections, architecture reviews, requirements reviews, and pull-request review can detect ambiguity, incorrect assumptions, security weaknesses, duplicated logic, and maintainability problems early.

A structured review asks:

  • Is the requirement complete, consistent, feasible, and testable?
  • Are error paths and boundary conditions addressed?
  • Does the design respect security, privacy, accessibility, and performance constraints?
  • Is the implementation understandable and consistent with project standards?
  • Are tests meaningful and sufficient for the risk?

A defect report should include a concise summary, environment and version, reproducible steps, expected and actual results, evidence, severity, priority, and affected component. Severity describes the technical or user impact; priority describes how urgently the defect should be addressed. A defect can have high severity but lower immediate priority if it affects a rarely used feature that is temporarily disabled.

Typical workflow states are New, Triaged, In Progress, Resolved, Ready for Verification, Verified, Closed, or Reopened. Triage should consider duplicates, reproducibility, release risk, workarounds, and ownership.

A useful defect metric is defect density:

Defect density = Number of confirmed defects ÷ Size of software

Size may be measured in thousands of lines of code, function points, requirements, or another agreed unit. Comparisons are valid only when the measurement method, scope, maturity, and reporting practices are comparable. Defect counts alone can reward under-reporting and should never be used as a simple ranking of developers.

Root-cause analysis distinguishes the visible defect from the process or technical condition that allowed it. Techniques include the five whys, cause-and-effect diagrams, causal analysis, and examination of escaped defects. Corrective action may involve changing requirements, adding a review checklist, improving test data, redesigning an interface, or strengthening deployment controls.

6. A Full-Stack Quality Case

Illustrative case: Campus Market

Background. Campus Market is a web application through which students purchase event tickets. It contains a React frontend, a REST API, a relational database, an email service, and a payment provider.

Problem. During a pilot release, some users were charged twice when they refreshed the payment page. Other users received confirmation emails even though payment had failed. The application also became slow when ticket sales opened.

Analysis. A risk workshop identified payment duplication and incorrect confirmation as high-impact risks because they could cause financial loss and reputational damage. Load-related delay was also high risk because demand was concentrated at event launch. Investigation found that the payment request was not idempotent, the email service reacted to an intermediate status, and the test environment used a much smaller database and workload.

Approach. The team implemented an idempotency key for each payment attempt and added a unique database constraint for the provider transaction identifier. Payment state changes were modeled explicitly, and confirmation emails were sent only after a verified successful state. The test strategy included:

  • unit tests for state transitions, currency calculations, and retry logic;
  • integration tests with a payment-provider sandbox and realistic database constraints;
  • contract tests for frontend–API response formats;
  • system tests for successful, declined, interrupted, and repeated payment flows;
  • performance tests using expected opening-time traffic and larger data volumes;
  • acceptance tests with student representatives;
  • regression tests for refunds and ticket inventory;
  • observability checks for duplicate attempts, failed callbacks, latency, and queue depth.

The team also reviewed the design, conducted threat modeling, and established release gates requiring no unresolved critical payment defects.

Outcome. Repeated requests no longer created duplicate charges, failed payments no longer triggered confirmations, and capacity testing exposed a database indexing problem before production release. The application still required monitoring because tests could not reproduce every provider outage or user network condition.

Learning points. The case demonstrates that quality is cross-functional. A unit test alone could not reveal the interaction among browser refreshes, payment retries, database constraints, and email timing. Risk prioritization directed effort toward financial correctness and realistic operational load. It also demonstrates that quality continues after release through monitoring, incident review, and controlled improvement.

7. Quality Models, Metrics, and Governance

A quality model gives teams a shared vocabulary. ISO/IEC 25010 is widely used as a reference for software product quality characteristics, although organizations must tailor it to their context. Quality models do not automatically produce quality; they help teams make expectations explicit and measurable.

Useful measures may include:

  • escaped defects by severity;
  • automated test pass rate and duration;
  • branch or requirements coverage;
  • change failure rate and recovery time;
  • availability and percentile latency;
  • accessibility conformance findings;
  • unresolved security vulnerabilities;
  • mean time to detect and mean time to restore.

Metrics should support decisions, not become targets detached from outcomes. For example, demanding 100% code coverage may lead developers to write superficial tests, while monitoring escaped defects and mutation results may better reveal test effectiveness.

Governance requires traceability between risks, requirements, design elements, test cases, defects, and release decisions. For regulated or safety-sensitive products, evidence may need to be retained, independently reviewed, access-controlled, and auditable. Privacy laws and security obligations also affect test data: production personal data should not be copied casually into development environments. Synthetic or properly anonymized data should be used, with re-identification risk considered.

8. Contemporary Issues and Limitations

Modern development introduces distributed systems, microservices, cloud infrastructure, mobile clients, third-party dependencies, feature flags, and AI-assisted coding. These increase the number of behaviors and environments that must be considered.

AI tools can generate test cases, summarize failures, suggest assertions, and identify likely defects. However, generated tests may encode incorrect assumptions, miss business context, reproduce implementation details, or create a false impression of coverage. Developers remain responsible for reviewing generated code, protecting confidential data, checking licensing implications, and validating outputs against requirements.

Testing has fundamental limits. It can demonstrate the presence of defects but cannot generally prove their absence for a non-trivial system. Passing tests may reflect incomplete requirements, untested environments, insufficient data, or weak assertions. Quality therefore depends on complementary practices: sound architecture, clear requirements, reviews, security engineering, observability, operational readiness, and responsible decision-making.

Best practices

  1. Start testing from risks and requirements, not from code coverage targets.
  2. Test early and continuously, while retaining realistic system and acceptance tests.
  3. Use multiple test levels because no single level detects every defect class.
  4. Prefer deterministic automation with strong diagnostics.
  5. Test boundaries, failures, retries, permissions, accessibility, and degraded operation.
  6. Keep test environments and data representative of production risks.
  7. Treat defects as learning opportunities and address systemic causes.
  8. Combine quantitative metrics with expert judgment and user evidence.
  9. Protect personal, financial, and confidential test data.
  10. Monitor quality after release and feed operational evidence back into development.

Chapter Summary

Verification determines whether software artifacts conform to specified requirements and designs; validation determines whether the product is fit for real use. Software quality includes functionality, performance, reliability, usability, security, maintainability, accessibility, compatibility, and portability.

A risk-based strategy prioritizes testing according to likelihood and impact. Unit, integration, system, acceptance, regression, performance, usability, accessibility, and security testing serve different purposes and must be combined. Automation provides rapid feedback, but human review, exploratory testing, and user evaluation remain essential.

Coverage measures describe exercised behavior rather than correctness. Reviews detect problems before execution, while defect management organizes discovery, prioritization, verification, and learning. Quality models and metrics create shared expectations, but metrics must be interpreted carefully. Finally, quality is a lifecycle responsibility extending from requirements through operation, monitoring, and continuous improvement.

Key Terms

Verification: Checking whether an artifact conforms to specified requirements or standards.

Validation: Checking whether a product is fit for its intended use.

Quality assurance: Process-oriented activities that prevent defects and improve development practices.

Quality control: Product-oriented activities that identify defects in a software product.

Risk-based testing: Allocating test effort according to likelihood and consequence of failure.

Unit testing: Testing an isolated, small software component.

Integration testing: Testing interactions among components or systems.

System testing: Testing the complete integrated application.

Acceptance testing: Evaluating whether stakeholders accept the product for intended use.

Regression testing: Checking that changes have not damaged existing behavior.

Performance testing: Evaluating responsiveness, throughput, resource use, and stability.

Usability testing: Observing users performing realistic tasks to evaluate ease and effectiveness.

Test automation: Using software tools to execute tests and report results.

Test coverage: A measure of the program elements or requirements exercised by tests.

Mutation testing: Assessing test strength by inserting controlled changes into code.

Defect severity: The impact of a defect on the system or users.

Defect priority: The urgency with which a defect should be addressed.

Traceability: The ability to relate requirements, risks, tests, defects, and release evidence.

Flaky test: A test whose result changes without a relevant product change.

Residual risk: Risk remaining after controls and mitigations have been applied.

Review Questions

Short Answer Questions

  1. Distinguish verification from validation and provide one example of each.
  2. Why is risk exposure useful when planning a test strategy?
  3. What is the purpose of regression testing?
  4. Why does high statement coverage not prove software correctness?
  5. Distinguish defect severity from defect priority.

Long Answer Questions

  1. Explain the roles of unit, integration, system, and acceptance testing in a full-stack application.
  2. Discuss the benefits and limitations of automated testing and the test pyramid.
  3. Explain how reviews, testing, defect management, and root-cause analysis contribute to quality assurance.
  4. Describe a comprehensive performance and usability test strategy for an online service.
  5. Evaluate how quality models and metrics can improve decision-making without encouraging harmful gaming of measures.

Analytical / Application Questions

  1. A university registration system occasionally enrolls students in a full course while displaying a payment error. Develop a risk-based investigation and test plan covering technical and user risks.
  2. An API has 90% statement coverage but frequent production failures involving authorization and timeouts. Analyze why the coverage figure is insufficient and propose additional tests and metrics.
  3. Design a release quality gate for a ticketing application that includes functional, security, performance, accessibility, defect, and residual-risk criteria. Justify each criterion.

Multiple Choice Questions with Answers

Question 1

Which statement best distinguishes validation from verification?

A. Validation checks whether code follows formatting rules.

B. Validation checks whether the product is fit for intended use.

C. Validation measures only branch coverage.

D. Validation replaces acceptance testing.

Correct Answer: B. Validation checks whether the product is fit for intended use.

Question 2

Which test level primarily examines an isolated function or class?

A. System testing

B. Acceptance testing

C. Unit testing

D. Performance testing

Correct Answer: C. Unit testing

Question 3

A risk-based strategy primarily prioritizes testing according to which factors?

A. Code length and number of developers

B. Probability and impact of failure

C. Number of screens and database tables

D. Average test execution time only

Correct Answer: B. Probability and impact of failure

Question 4

What is the main purpose of regression testing?

A. To test only newly written code

B. To measure user satisfaction

C. To verify that changes have not broken existing behavior

D. To replace requirements analysis

Correct Answer: C. To verify that changes have not broken existing behavior

Question 5

Which technique is especially suitable for testing values at and around an input limit?

A. Boundary-value analysis

B. Mutation testing

C. Load balancing

D. Static deployment

Correct Answer: A. Boundary-value analysis

Question 6

A test executes 80 of 100 identified statements. What is the statement coverage?

A. 20%

B. 50%

C. 80%

D. 125%

Correct Answer: C. 80%

Question 7

Which statement about code coverage is correct?

A. 100% statement coverage proves there are no defects.

B. Coverage measures which code elements were exercised, not whether assertions are adequate.

C. Coverage can only be measured manually.

D. Coverage makes acceptance testing unnecessary.

Correct Answer: B. Coverage measures which code elements were exercised, not whether assertions are adequate.

Question 8

What does a flaky test do?

A. Always fails because of a known defect

B. Changes its result without a relevant product change

C. Tests only database performance

D. Measures mutation score

Correct Answer: B. Changes its result without a relevant product change

Question 9

Which statement correctly distinguishes severity and priority?

A. Severity concerns impact; priority concerns urgency.

B. Severity concerns urgency; priority concerns impact.

C. They always have identical values.

D. Neither is useful during defect triage.

Correct Answer: A. Severity concerns impact; priority concerns urgency.

Question 10

Which practice most directly protects sensitive information in test environments?

A. Copying all production data into every developer laptop

B. Disabling access controls during testing

C. Using suitable synthetic or properly anonymized test data

D. Removing all negative tests

Correct Answer: C. Using suitable synthetic or properly anonymized test data

Software Engineering Principles
Chapter 8 of 15