This page describes the testing infrastructure, fixture-based testing approach, and validation tools used in the gobl.cii repository. It covers test organization, the -update and -validate flags, helper functions, and how to run the complete test suite.
For information about Phive service integration and VESID identifiers used in validation, see Validation Tools. For CI/CD workflows that execute these tests automatically, see CI/CD Pipeline.
The test suite uses fixture-based golden file testing combined with optional external validation:
| Strategy | What it checks | Enabled by |
|---|---|---|
| Unit assertions | Individual struct fields produced by conversion functions | Always |
| Golden-file comparison | Full XML/JSON output matches stored reference files | Always |
| Phive validation | Generated CII XML passes standards-specific validation rules | -validate flag |
Tests live in the root package (files named *_test.go) and use the cii_test external test package to exercise only the exported API. Two primary test functions drive the suite: TestConvertToInvoice for GOBL→CII conversion and TestParseInvoice for CII→GOBL parsing.
Sources: examples_test.go1-23 examples_test.go40-122 examples_test.go124-209 README.md127-148
All test fixtures are stored under test/data/ with separate subdirectories for each e-invoicing standard. The structure supports bidirectional testing.
test/
└── data/
├── convert/ # GOBL → CII conversion tests
│ ├── en16931/
│ │ ├── invoice-de-de.json
│ │ ├── invoice-complete.json
│ │ ├── correction-invoice.json
│ │ ├── credit-note.json
│ │ └── out/
│ │ ├── invoice-de-de.xml ← golden output
│ │ ├── invoice-complete.xml
│ │ └── ...
│ ├── xrechnung/
│ │ ├── *.json
│ │ └── out/*.xml
│ ├── facturx/
│ ├── peppol/
│ ├── choruspro/
│ ├── peppol-france-facturx/
│ ├── peppol-france-cius/
│ └── zugferd/
└── parse/ # CII → GOBL parsing tests
├── en16931/
│ ├── *.xml
│ └── out/*.json ← golden output
├── xrechnung/
├── facturx/
├── peppol/
├── choruspro/
├── peppol-france-facturx/
├── peppol-france-cius/
└── peppol-france-extended/
Directory Structure:
test/data/convert/<standard>/*.json — GOBL envelope input files for conversion testingtest/data/convert/<standard>/out/*.xml — Golden CII XML output filestest/data/parse/<standard>/*.xml — CII XML input files for parsing testingtest/data/parse/<standard>/out/*.json — Golden GOBL JSON output filesEach standard directory contains examples specific to that context's requirements and validation rules.
Sources: examples_test.go24-32 examples_test.go54-68 examples_test.go126-138 examples_test.go268-287
Three package-level helper functions are defined in examples_test.go and shared across all component test files in the cii_test package. These helpers abstract fixture loading and conversion operations.
Diagram: Test Helper Function Flow
loadEnvelope(t *testing.T, name string) *gobl.EnvelopeLoads a GOBL envelope from test/data/convert/<name>, unmarshals the JSON, normalizes UUIDs to staticUUID for deterministic comparison, calculates totals, validates the envelope, and optionally writes it back if -update flag is set.
Implementation details:
dataPath(pathConvert, name) to construct full pathenv.Head.UUID and inv.UUID to static value 0195ce71-dc9c-72c8-bf2c-9890a4a9f0a2env.Calculate() and env.Validate() before returning-update is trueSources: examples_test.go230-253 examples_test.go31
newInvoiceFrom(t *testing.T, name string) (*cii.Invoice, error)Convenience wrapper that loads a GOBL envelope via loadEnvelope and immediately converts it to a CII Invoice using cii.ConvertInvoice with default context. Returns the *cii.Invoice and any conversion error. This is the primary helper for unit tests that assert individual struct fields.
Sources: examples_test.go212-216 settlement_test.go14 lines_test.go12 header_test.go19
parseInvoiceFrom(t *testing.T, name string) (*gobl.Envelope, error)Loads a CII XML file from test/data/parse/<name>, calls cii.Parse(data), and returns the resulting GOBL envelope. Used for CII→GOBL parsing tests to verify reverse conversion.
Sources: examples_test.go219-227 settlement_parse_test.go15 settlement_parse_test.go54
Unit tests verify individual fields on the structs returned by newInvoiceFrom or parseInvoiceFrom. They use github.com/stretchr/testify/assert (non-fatal) and github.com/stretchr/testify/require (fatal on failure).
Diagram: Unit Test Structure for GOBL → CII Direction
Sources: settlement_test.go12-64 lines_test.go10-30 cii_test.go12-57
The test calls newInvoiceFrom(t, "en16931/invoice-de-de.json") and then makes assertions on fields such as doc.Transaction.Settlement.Currency, doc.Transaction.Settlement.PaymentTerms[0].Description, and summary amounts. This approach validates the internal struct state before any XML serialization.
Tests for the XRechnung context call cii.ConvertInvoice(env, cii.WithContext(cii.ContextXRechnungV3)) and assert the exact URN strings in out.ExchangedContext.GuidelineContext.ID and out.ExchangedContext.BusinessContext.ID.
Golden-file tests verify that conversion output matches byte-for-byte against stored reference files. This approach makes unintended output changes immediately visible and provides a comprehensive regression suite.
Diagram: Golden-File Test Execution Flow
TestConvertToInvoice iterates through all contexts (EN16931, Peppol, XRechnung, etc.) and for each context:
filepath.Glob to find all *.json files in test/data/convert/<context>/loadEnvelope(t, filepath) to get normalized GOBL datacii.ConvertInvoice(env, cii.WithContext(ctx)) with the context-specific Contextdoc.Bytes() to generate XML bytes-update flag is set, writes bytes to out/<filename>.xml (creates directory if needed)out/<filename>.xml and asserts byte equality using assert.EqualSources: examples_test.go40-122 examples_test.go70-119
TestParseInvoice follows a similar pattern for reverse conversion:
*.xml files in test/data/parse/<context>/cii.Parse(xmlData) to convert CII to GOBLstaticUUID, recalculates totals-update flag is set, marshals envelope to JSON and writes to out/<filename>.jsonassert.JSONEqThe use of assert.JSONEq instead of byte comparison allows for whitespace and field order differences while still catching semantic changes.
Sources: examples_test.go124-209 examples_test.go149-206
When conversion logic changes intentionally, regenerate all golden files:
This flag is defined via flag.Bool and checked throughout the test suite to conditionally write output files. After updating, review the diffs in version control to confirm only expected changes occurred.
Sources: examples_test.go35 examples_test.go93-99 examples_test.go169-178 README.md135-139
The -validate flag enables optional external validation of generated CII XML against standards-specific validation rules through the Phive gRPC service. This provides an additional layer of compliance verification beyond golden-file comparison.
Diagram: Phive Validation Flow
The validation logic is implemented directly in TestConvertToInvoice:
-validate flag is set, establishes gRPC connection to localhost:9091 at test startctx.VESID != "":
phive.ValidateXmlRequest with the context's VESID identifier and XML bytespc.ValidateXml(context.Background(), request)resp.Success == true, printing full validation results JSON on failureEach Context struct contains a VESID field that maps to a specific Phive validation artifact set:
| Context | VESID |
|---|---|
ContextEN16931V2017 | (empty - no validation) |
ContextXRechnungV3 | de.xrechnung:cii:3.0 |
ContextPeppolV3 | eu.peppol.bis3:invoice:3.0 |
ContextFacturXV1 | fr.factur-x:cii:1.0 |
The VESID is used by Phive to select the appropriate Schematron rules and business rules for validation.
Sources: examples_test.go38 examples_test.go44-52 examples_test.go102-112 README.md141-147
Start the Phive service, then run tests with the -validate flag:
If the Phive service is not available, the test will fail when attempting gRPC connection. The validation is entirely opt-in via the flag.
Sources: examples_test.go44-52 README.md141-147
| Library | Import path | Purpose |
|---|---|---|
testify/assert | github.com/stretchr/testify/assert | Non-fatal field assertions, golden-file comparison |
testify/require | github.com/stretchr/testify/require | Fatal assertions (stops test on failure) |
phive | github.com/invopop/phive | gRPC client for Phive validation service |
gobl | github.com/invopop/gobl | GOBL envelope and invoice structures |
grpc | google.golang.org/grpc | gRPC connection for Phive service |
Sources: examples_test.go13-22 settlement_test.go6-9 lines_test.go6-7
Run all tests without external validation:
This executes all unit tests, component tests, and golden-file comparison tests. Phive validation is skipped.
Regenerate all golden output files after intentional changes:
This writes new golden files to:
test/data/convert/<standard>/out/*.xml (GOBL→CII direction)test/data/parse/<standard>/out/*.json (CII→GOBL direction)Review diffs in version control before committing.
Sources: README.md135-139 examples_test.go35 examples_test.go93-99 examples_test.go169-178
Enable standards compliance validation (requires running Phive service):
The test suite connects to Phive via gRPC and validates generated CII XML against the VESID specified in each context. Failures include full validation report JSON.
Sources: README.md141-147 examples_test.go38 examples_test.go44-52 examples_test.go102-112
Update and validate simultaneously:
Generate coverage profile for CI/CD or local analysis:
The CI workflow uses -race and -coverprofile flags; see CI/CD Pipeline.
Sources: README.md129-133
The following diagram shows which test files cover which conversion functions.
Sources: cii_test.go12-57 settlement_test.go12-64 lines_test.go10-30 party_parse_test.go15-108
Refresh this wiki