Independent and not affiliated with the FDA, MHRA, ISPE, PDA, or any agency. Get the appgoutham@madhadi.com
madhadi.comData Integrity & GxP Quality
Browse all topics → Articles Templates & Procedures Learning paths GlossaryScenariosToolsRegulatory ReferencesLearning PathsTopics About Start here
Protocol Plug-and-play starting point CSV / CSA

Protocol: OQ for GAMP Category 5 Custom Software (Black-Box, White-Box, Boundary)

A plug-and-play OQ test protocol for GAMP Category 5 custom software that combines black-box functional testing against the FS, white-box structural testing against the DS algorithm's branches, systematic boundary value analysis, and concurrent-access testing, with a branch-coverage traceability table and a filled specimen.

Document type: Protocol

Read and copy the template below into your own quality system. It is a generic starting point for your own internal use, provided as is, with no warranty; see the Terms and License. Adopting it does not by itself create compliance.

This is a ready-to-use Operational Qualification (OQ) protocol for GAMP Category 5 custom software: it is written for systems where the custom logic’s internal branches, not just its external behavior, need to be exercised and confirmed against an independently derived expected result. Replace every <<FILL: ...>> placeholder with your own specifics, approve the protocol before execution, and record actual results and evidence at the time of execution. A worked filled specimen follows. This content is educational reference, not legal or regulatory advice; verify each cited regulation against the current source before you rely on it.

This protocol assumes the Design Specification, code review, and unit testing described in validating custom software: GAMP Category 5 from specification to release are already complete; see Specification: Design Specification (DS) for Custom GxP Software and Record: Unit Test Record for GxP Custom Software for those upstream deliverables. This protocol tests the integrated, deployed system; it does not replace either of them. For a general-purpose computerized system OQ across all GAMP categories, see computerized system OQ protocol; for verification testing scoped to a standalone script, notebook, or dashboard, see verification testing of a GxP script, notebook, or dashboard. This protocol is for a Category 5 system where structural branch coverage against the DS, not just functional testing against the FS, is required.

Approval page

Testing does not begin until this page is signed.

FieldEntry
Protocol titleOQ, <<FILL: system / component name>>
Protocol number<<FILL: OQ-ID>>
Version<<FILL>>
FS reference and version<<FILL>>
DS reference and version<<FILL>>
Version / commit under testTag <<FILL>> at commit <<FILL>>
Governing procedure<<FILL: SOP-ID>>

Pre-execution approvals

RoleNameSignatureDate
Author of protocol<<FILL>>
System owner<<FILL>>
Validation lead / CSV<<FILL>>
Quality Assurance<<FILL>>

Post-execution approvals

RoleNameSignatureDate
Executed by<<FILL>>
Reviewed by (independent of executor)<<FILL>>
Validation lead / CSV<<FILL>>
Quality Assurance<<FILL>>

1. Objective

To verify that <<FILL: system / component name>>, at the version identified above, satisfies its functional specification from the outside (black-box), executes every significant internal branch of its DS-specified algorithm correctly (white-box), behaves correctly at every input boundary, and, where applicable, handles concurrent access correctly, and to record evidence sufficient to support release for its intended GxP use.

2. Scope

In scope: the functions, modules, and workflows of <<FILL: system / component name>> listed in section 7, at the version named on the approval page.

Out of scope, with the control that covers each:

Out of scopeCovered by
Unit-level testing of individual functions during development<<FILL: unit test record reference>>
Independent code review confirming the code implements the DS<<FILL: code review record reference>>
Installation of the software and environment<<FILL: IQ protocol reference>>
End-to-end use under real operating conditions with trained users<<FILL: PQ/UAT protocol reference>>

3. System description

FieldEntry
What the system does<<FILL: two sentences>>
GxP decision(s) supported<<FILL>>
GAMP category and rationale<<FILL: 5, or the Category 5 component of a hybrid system>>
Environment identifier<<FILL: manifest file, package snapshot, or image digest>>
Test environment relationship to production<<FILL: identical / stated differences and justification>>
Concurrent-access applicable?Yes/No, <<FILL: if yes, name the concurrency model, e.g. multiple simultaneous users, or a real-time polling process>>

4. Prerequisites

#PrerequisiteConfirmedEvidence reference
P1FS and DS are approved and current; this protocol traces to their requirement and algorithm IDs<<FILL>><<FILL>>
P2The version under test is tagged in version control and matches the tag on the approval page<<FILL>><<FILL>>
P3Independent code review for this version is complete with no open Critical or Major findings<<FILL>><<FILL>>
P4Unit testing for this version is complete and passed, per the unit test record<<FILL>><<FILL>>
P5Every conditional branch and error handler named in the DS is listed in section 8 before execution begins<<FILL>><<FILL>>
P6Expected results for every white-box and black-box known-answer case were derived independently of the code and recorded before execution<<FILL>><<FILL>>
P7Test environment is pinned and matches production in every respect that could affect the result, or the difference is assessed<<FILL>><<FILL>>
P8Testers are trained on this protocol and the governing procedure<<FILL>><<FILL>>

5. Roles

RoleResponsibility during execution
TesterExecutes each test case exactly as written, records the actual result verbatim, attaches evidence
Independent verifier of expected resultsDerived and recorded expected results before execution, by hand calculation or an independent tool, distinct from the code under test
ReviewerReviews executed cases for completeness and correct pass/fail determination; independent of the tester
System ownerAvailable to clarify intended behavior; does not determine pass or fail
Validation lead / CSVAdjudicates deviations, approves the summary
Quality AssuranceApproves the protocol before execution and the summary after

6. Acceptance criteria

#Criterion
AC1Every black-box test case in section 7 is executed with an actual result and evidence recorded
AC2Every branch and error handler listed in the branch-coverage matrix in section 8 is exercised by at least one test case, with a pass result
AC3Every boundary value case in section 9 returns the specified value, including rejection at values just outside the valid range
AC4Where concurrent access applies, every case in section 10 passes with no data corruption, no lost update, and correct session handling
AC5Every known-answer expected result agrees with an independently derived value, not a value produced by the code under test
AC6Every requirement and every DS branch traces to at least one executed test case with no untested item
AC7Every deviation is documented, assessed, and closed before the protocol is concluded
AC8The executed protocol is reviewed and approved by a person independent of the tester

7. Black-box functional test cases (against the FS)

Test IDFS requirementCase typeInputExpected resultActualPass/FailTesterDate
<<FILL: TC-BB-001>><<FILL>>Normal<<FILL>><<FILL>>
<<FILL: TC-BB-002>><<FILL>>Boundary<<FILL>><<FILL>>
<<FILL: TC-BB-003>><<FILL>>Error<<FILL>><<FILL: specified error, no partial result>>

8. White-box structural test cases (against the DS algorithm’s branches)

Every conditional branch, every error handler, and every derived flag named in the DS algorithm specification gets a row here, and each row’s expected value is derived independently of the code, per the DS’s own worked example or a fresh hand calculation, not by running the function and reading its output.

DS branch / condition IDDescription (from DS)Test IDInput designed to hit this branchIndependently derived expected resultActualPass/Fail
<<FILL: e.g. ALG-001 step 1>><<FILL: e.g. load mass = 0 raises ERR-ALG-001>><<FILL: TC-WB-001>><<FILL>><<FILL>>
<<FILL: e.g. ALG-001 step 6, LOW_YIELD>><<FILL>><<FILL: TC-WB-002>><<FILL>><<FILL>>
<<FILL: e.g. ALG-001 step 6, HIGH_YIELD>><<FILL>><<FILL: TC-WB-003>><<FILL>><<FILL>>
<<FILL: e.g. ALG-001 step 6, IMPLAUSIBLE>><<FILL>><<FILL: TC-WB-004>><<FILL>><<FILL>>
<<FILL: e.g. ALG-001 step 6, NORMAL>><<FILL>><<FILL: TC-WB-005>><<FILL>><<FILL>>

8.1 Branch coverage completeness statement

FieldEntry
Total branches / conditions identified in the DS<<FILL: count>>
Branches exercised by a test case above<<FILL: count>>
Branches not covered, with justification<<FILL: none, or list and justify each>>

A DS branch with no corresponding row above is either untested or the DS was incomplete; neither is acceptable at protocol conclusion.

9. Boundary value analysis

For every numeric parameter the system accepts, test at the minimum valid value, the maximum valid value, one value below the minimum, and one value above the maximum. For string or count fields, test at minimum length, maximum length, and empty.

ParameterMinimum validMaximum validJust below minimum (expect reject)Just above maximum (expect reject)ActualPass/Fail
<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>
<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

10. Concurrent access testing (execute where section 3 marks this applicable)

Test IDScenarioExpected resultActualPass/Fail
<<FILL: TC-CC-001>>Two users submit the same record simultaneouslyOnly one succeeds, or the system serializes correctly; no duplicate or corrupted record
<<FILL: TC-CC-002>>One user reads a record while another modifies itReading user sees a consistent state, not a partial write
<<FILL: TC-CC-003>>Session exceeds the configured timeoutSession terminated; re-authentication required before further action

Mark this section “Not applicable, single-user batch execution confirmed” if section 3 states concurrency does not apply, and state the basis for that conclusion.

11. Deviation handling

  1. A test case whose actual result does not match the expected result is recorded as Fail. The expected result, the input, or the code is not adjusted to obtain a pass.
  2. Every failure raises a deviation under <<FILL: SOP-ID>>, recording the test ID, expected, actual, evidence, and the immediate assessment of whether other executed cases are affected.
  3. The validation lead classifies each deviation as a code defect, a DS defect, or a protocol/expected-result defect, and dispositions accordingly.
  4. A deviation is closed only when the corrective action is complete, affected cases are re-executed and pass, and closure is approved by the validation lead and QA.
Deviation IDTest IDDescriptionClassificationCorrective actionRe-executedClosed
<<FILL>><<FILL>><<FILL>><<FILL>><<FILL>><<FILL>><<FILL>>

12. Traceability

Requirement / branch IDTest case ID(s)ExecutedResult
<<FILL>><<FILL>><<FILL>><<FILL>>

Untested requirements or branches: <<FILL: none, or ID and justification>>

13. Summary and conclusion

FieldEntry
Black-box cases executed / passed<<FILL>>
White-box branch cases executed / passed<<FILL>>
Branch coverage achieved<<FILL: e.g. 100%, or state gaps>>
Boundary cases executed / passed<<FILL>>
Concurrent-access cases executed / passed (or N/A)<<FILL>>
Deviations raised / open at conclusion<<FILL: open should be zero>>
Version at conclusionTag <<FILL>> at commit <<FILL>>

Conclusion statement: <<FILL: state whether the system, at the identified version, is verified against its FS and DS and suitable to proceed to PQ/UAT, and name any limitation>>

14. Attachments

#Attachment
AApproved FS and DS
BIndependent code review record
CUnit test record
DIndependently derived expected results, dated before execution
ETest evidence (screenshots, output files, logs)
FDeviation records

15. References

21 CFR 211.68 (automatic, mechanical, and electronic equipment). 21 CFR Part 11 (electronic records and signatures). ISPE GAMP 5 (Second Edition), for the Category 5 verification expectation (reference by title; describe, do not paste). FDA guidance, Computer Software Assurance for Production and Quality Management System Software (current version).

Confirm the current version and clause numbers of each reference before issue.

16. Revision history

VersionDateAuthorSummary of change
<<FILL: 1.0>><<FILL: date>><<FILL: author>>Initial issue.

Filled specimen

The following shows an extract of an OQ executed for the step-yield calculation script referenced in the Design Specification example (DS-CUST-014, algorithm ALG-001), version tagged v1.3.0, commit 9e21ab4, executed 22 August 2026. Numbers are illustrative.

Black-box (extract)

Test IDFS requirementCaseInputExpectedActualPass/Fail
TC-BB-001FS-040, yield calculationNormalload_titer=12.5, load_vol=400, pool_titer=8.2, pool_vol=55090.2% displayed on the batch record90.2%Pass
TC-BB-002FS-041, audit trail on calculationNormalSame as aboveAudit entry: timestamp, operator, batch ID, resultEntry present with all four fieldsPass

White-box branch coverage (extract)

DS branchDescriptionTest IDInputExpectedActualPass/Fail
ALG-001 step 1load_mass = 0 raises ERR-ALG-001TC-WB-001load_titer=0, load_vol=400, pool_titer=8.2, pool_vol=550ERR-ALG-001 raised, no result writtenERR-ALG-001 raisedPass
ALG-001 step 6, LOW_YIELDyield < 70.0 sets result_flag = LOW_YIELDTC-WB-002inputs giving yield = 65.0% (hand-calculated)result_flag = LOW_YIELDLOW_YIELDPass
ALG-001 step 6, boundary at 70.0yield = 70.0 exactly is NORMAL, not LOW_YIELDTC-WB-003inputs giving yield = 70.0% exactly (hand-calculated)result_flag = NORMALNORMALPass
ALG-001 step 6, HIGH_YIELDyield > 110.0 sets result_flag = HIGH_YIELDTC-WB-004inputs giving yield = 120.0%result_flag = HIGH_YIELDHIGH_YIELDPass
ALG-001 step 6, IMPLAUSIBLEyield > 150.0 sets result_flag = IMPLAUSIBLE, held pending reviewTC-WB-005inputs giving yield = 155.0%result_flag = IMPLAUSIBLE, held from batch recordIMPLAUSIBLE, heldPass

Branch coverage completeness: 5 branches identified in DS-CUST-014 ALG-001 (zero-mass error, LOW_YIELD, the 70.0 boundary, HIGH_YIELD, IMPLAUSIBLE), 5 exercised, 0 gaps.

Boundary value analysis (extract)

ParameterMin validMax validBelow minAbove maxActualPass/Fail
load_titer_mg_ml0.01999.990 (reject)1000.00 (reject)Both rejected with field-specific messagePass

Concurrent access

Test IDScenarioExpectedActualPass/Fail
TC-CC-001Two operators submit a yield calculation for the same batch ID within one secondSecond submission rejected with “calculation already in progress for this batch,” first completes normallyBehaved as expectedPass

In this example, the branch-coverage table is what separates this protocol from a functional test alone: TC-WB-003 specifically targets the boundary the DS calls out explicitly (yield at exactly 70.0 is NORMAL, not LOW_YIELD), a case a black-box-only test plan would very likely never generate, because nothing about normal use produces a value at exactly a threshold.

Common inspection findings this protocol prevents

  • OQ testing covers the functional specification but never exercises the internal branches of a custom algorithm, so a wrong comparison operator (< instead of <=) at a threshold is never caught.
  • The exact boundary values named in the DS were never tested, only “typical” values near them.
  • Expected results for calculation test cases were read from the system’s own output rather than derived independently.
  • A DS names an error-handling branch that has no corresponding test case anywhere in the validation package.
  • Concurrent-access behavior was never tested for a multi-user system, and a race condition first appears in production.
  • The branch-coverage claim in the validation summary is asserted with no table showing which branches were actually exercised.

How to adapt this protocol

  1. Set your protocol number, FS and DS references, and the version under test on the approval page.
  2. Build section 7 from your FS requirements and section 8 by walking through every conditional and error-handling branch named in your DS, one row per branch.
  3. Derive every white-box expected result independently, before execution, using the DS’s own worked example as a starting point where one exists.
  4. Complete section 9 for every numeric or length-bounded input your system accepts.
  5. Mark section 10 not applicable only after confirming, and stating the basis, that the system genuinely has no concurrent-access exposure.
  6. Complete the branch coverage completeness statement in section 8.1 before concluding the protocol; an unexplained gap blocks release.
  7. Confirm every regulation in section 15 against the current published version before issue.
Use madhadi.com as an app Full screen, works offline, one tap from your home screen.