Version: v1.0.0
Status: Draft
SRS Source: docusaurus/docs/srs/rules/rule-rquant.md
Rule Name: RQUANT
Domain: RULES-RQUANT
Overview
This document specifies tests for the RQUANT rule using decision tables and test vectors. The rule evaluates sample quantities against configured quantity group thresholds (Groups 2-9) and determines the appropriate reporting format including rounding precision, scientific notation, and detection thresholds.
Rule Characteristics:
- Pure business logic (no UI)
- Tiered decision tree with 9 quantity groups
- Specimen-type-based configuration selection
- Placeholder-based reporting output
- Error handling for missing configuration
Test Method: TM-API (per Test Plan - Rules use automated API tests)
Verification Approach:
Rule verification is performed using data-driven test vectors. Each row in a decision table represents a complete verification scenario with defined inputs and expected outputs. This format enables exhaustive condition coverage while remaining concise and auditable.
Coverage Summary
| REQ ID | Title | Conditions | Test Vectors | Coverage | Gaps |
|---|
| REQ-RULES-RQUANT-001 | Evaluate and Format Sample Quantities | 18 | 26 | 100% | None |
| REQ-RULES-RQUANT-002 | Handle Missing Configuration | 3 | 4 | 100% | None |
| REQ-RULES-RQUANT-003 | Select Reporting Configuration by Specimen Type | 6 | 8 | 100% | None |
Totals: 3 REQs, 27 Conditions, 38 Test Vectors, 100% Coverage
| Variable | Type | Valid Values | Description |
|---|
quantity | float | 0 to unlimited | Sample quantity value from PCR analysis |
target_id | int? | null, valid ID | Target identifier for the observation |
specimen_type | string | Plasma, Serum, ... | Sample material type |
use_sample_type | bool | true, false | System config for specimen-type selection |
Configuration Variables
| Variable | Type | Description |
|---|
group_2_threshold | float | Upper boundary for Group 2 (LoD) |
group_3_threshold | float | Upper boundary for Group 3 (no rounding) |
group_4_threshold | float | Upper boundary for Group 4 (boundary value) |
group_5_threshold | float | Upper boundary for Group 5 (1 sig fig) |
group_6_threshold | float | Upper boundary for Group 6 (2 sig figs) |
group_7_threshold | float | Upper boundary for Group 7 (3 sig figs) |
group_8_threshold | float | Upper boundary for Group 8 (2 sig figs) |
group_9_threshold | float | Upper boundary for Group 9 (sci notation) |
reporting_config.specimen_type | string | Specimen type for this config |
reporting_config.last_modified_at | datetime | Timestamp for fallback selection |
Output Variables
| Variable | Type | Description |
|---|
formatted_quantity | string | Formatted quantity for LIMS export |
error_code | string? | Error code (null if successful) |
{QUANT} | string | Placeholder value with applied rounding |
{LOQ} | string | Placeholder filled with applicable group limit |
Test configuration uses the following threshold values:
- Group 2: 100, Group 3: 500, Group 4: 1000, Group 5: 5000
- Group 6: 10000, Group 7: 100000, Group 8: 1000000, Group 9: 10000000
| TV | quantity | expected_format | format_rule | Covers |
|---|
| TV-001-001 | 50 | "Detected: <100" | Group 2: detected below LoD | AC: qty <= Group 2 |
| TV-001-002 | 100 | "Detected: <100" | Group 2: boundary inclusive | AC: qty = Group 2 |
| TV-001-003 | 250 | "250" | Group 3: no rounding | AC: Group 2 < qty <= Group 3 |
| TV-001-004 | 500 | "500" | Group 3: boundary inclusive | AC: qty = Group 3 |
| TV-001-005 | 750 | "1000" | Group 4: boundary value | AC: Group 3 < qty <= Group 4 |
| TV-001-006 | 1000 | "1000" | Group 4: boundary inclusive | AC: qty = Group 4 |
| TV-001-007 | 1040 | "1,000" | Group 5: 1 sig fig | AC: Group 4 < qty <= Group 5 |
| TV-001-008 | 2500 | "3,000" | Group 5: 1 sig fig (round up) | AC: 1 sig fig rounding |
| TV-001-009 | 5000 | "5,000" | Group 5: boundary inclusive | AC: qty = Group 5 |
| TV-001-010 | 2123 | "2,100" | Group 6: 2 sig figs | AC: Group 5 < qty <= Group 6 |
| TV-001-011 | 9999 | "10,000" | Group 6: 2 sig figs (round up) | AC: 2 sig fig rounding |
| TV-001-012 | 12927 | "12,900" | Group 7: 3 sig figs | AC: Group 6 < qty <= Group 7 |
| TV-001-013 | 99950 | "100,000" | Group 7: 3 sig figs (round up) | AC: 3 sig fig rounding |
| TV-001-014 | 1565323 | "1,600,000" | Group 8: 2 sig figs | AC: Group 7 < qty <= Group 8 |
| TV-001-015 | 1000000 | "1,000,000" | Group 8: boundary inclusive | AC: qty = Group 8 |
| TV-001-016 | 9982000 | "1.00E+07" | Group 9: sci notation 2 sig | AC: Group 8 < qty <= Group 9 |
| TV-001-017 | 10000000 | "1.00E+07" | Group 9: boundary inclusive | AC: qty = Group 9 |
| TV-001-018 | 15000000 | ">1.00E+07" | Exceeds Group 9 | AC: qty > Group 9 |
| TV-001-019 | 99999999 | ">1.00E+07" | Exceeds Group 9 (large) | AC: qty > Group 9 |
Decision Table: Placeholder Processing
| TV | template | quantity | loq_value | expected_output | Covers |
|---|
| TV-001-020 | "Report {QUANT}" | 1040 | 100 | "Report 1,000" | AC: {QUANT} substitution |
| TV-001-021 | "LOQ: {LOQ}" | 50 | 100 | "LOQ: 100" | AC: {LOQ} substitution |
| TV-001-022 | "Result: {QUANT}, LOQ: {LOQ}" | 2123 | 100 | "Result: 2,100, LOQ: 100" | AC: Combined placeholders |
Decision Table: Boundary Conditions (Edge Cases)
| TV | quantity | group_boundary | expected_behavior | Covers |
|---|
| TV-001-023 | 99.99 | Group 2 = 100 | "Detected: <100" | AC: Just below boundary |
| TV-001-024 | 100.01 | Group 2 = 100 | No rounding (Group 3) | AC: Just above boundary |
| TV-001-025 | 0 | Group 2 = 100 | "Detected: <100" | AC: Zero quantity |
| TV-001-026 | 0.001 | Group 2 = 100 | "Detected: <100" | AC: Very small quantity |
REQ-RULES-RQUANT-002: Handle Missing Configuration
Decision Table: Error Conditions
| TV | target_id | qty_groups_configured | expected_error | expected_output | Covers |
|---|
| TV-002-001 | null | N/A | RQUANT_LIMITS_MISSED | null | AC: target_id is null |
| TV-002-002 | 123 | false | RQUANT_LIMITS_MISSED | null | AC: Groups not configured |
| TV-002-003 | 123 | true | null | formatted value | AC: Valid configuration |
| TV-002-004 | 456 | partial (missing Group 5) | RQUANT_LIMITS_MISSED | null | AC: Incomplete config |
REQ-RULES-RQUANT-003: Select Reporting Configuration by Specimen Type
Decision Table: Configuration Selection Logic
| TV | use_sample_type | sample_specimen | configs_available | expected_config | Covers |
|---|
| TV-003-001 | true | Plasma | [Plasma, Serum] | Plasma config | AC: Match by specimen |
| TV-003-002 | true | Serum | [Plasma, Serum] | Serum config | AC: Match by specimen |
| TV-003-003 | false | Plasma | [Plasma(older), Serum(newer)] | Serum config | AC: Last modified wins |
| TV-003-004 | false | Serum | [Plasma(newer), Serum(older)] | Plasma config | AC: Last modified wins |
Decision Table: Specimen-Specific LOQ Values
Test scenario: HEV target with Plasma LOQ=430, Serum LOQ=228
| TV | use_sample_type | specimen | quantity | expected_outcome | Covers |
|---|
| TV-003-005 | true | Plasma | 113 | "Detected:<430" | AC: Plasma-specific LOQ |
| TV-003-006 | true | Serum | 113 | "Detected:<228" | AC: Serum-specific LOQ |
| TV-003-007 | false | Plasma | 113 | "Detected:<228" | AC: Falls back to last modified (Serum) |
| TV-003-008 | false | Serum | 113 | "Detected:<228" | AC: Falls back to last modified (Serum) |
Automation Status
| REQ ID | Test Vectors | Automation Status | Notes |
|---|
| REQ-RULES-RQUANT-001 | TV-001-001 to TV-001-026 | Automated | Quantity formatting |
| REQ-RULES-RQUANT-002 | TV-002-001 to TV-002-004 | Automated | Error handling |
| REQ-RULES-RQUANT-003 | TV-003-001 to TV-003-008 | Automated | Specimen selection |
Traceability to Existing Tests
| Requirement | Jira Tests | Status |
|---|
| REQ-RULES-RQUANT-001 | BT-5203 | Partial (18 TVs) |
| REQ-RULES-RQUANT-002 | BT-5203 | Partial (implicit) |
| REQ-RULES-RQUANT-003 | BT-5203 | Partial (TV-003-005, TV-003-006) |
Note: BT-5203 uses v2 config (Viracor 2.25.0.xlsx). No v3 RQUANT test available.
Gap Analysis
Identified Gaps
| Gap | Requirement | Description | Priority | Owner |
|---|
| GAP-001 | REQ-RULES-RQUANT-001 | BT-5203 covers 18 TVs; 12 TVs remain untested (boundary/rounding edge cases: TV-001-008 through TV-001-026) | High | TBD |
| GAP-002 | REQ-RULES-RQUANT-002 | BT-5203 provides implicit coverage for TV-002-003; TV-002-001, TV-002-002, TV-002-004 (error handling) untested | Medium | TBD |
| GAP-003 | REQ-RULES-RQUANT-003 | BT-5203 covers TV-003-005 (Plasma LOQ), TV-003-006 partial; TV-003-001 to TV-003-004, TV-003-007, TV-003-008 (specimen selection logic) untested | Medium | TBD |
- GAP-001: Expand v3 RQUANT test coverage for boundary conditions (TV-001-008, TV-001-009, TV-001-011 through TV-001-026)
- GAP-002: Create test scenarios for missing configuration error handling (TV-002-001, TV-002-002, TV-002-004)
- GAP-003: Create test scenarios for specimen-type selection logic (TV-003-001 through TV-003-004, TV-003-007, TV-003-008)