Base Canonical Tester
Overview
The baseCanonicalTester package provides a standardized framework for testing Data Integration Types and metadata. The Canonical Tester offers the following benefits:
- A "native" experience of authoring and running DI tests by allowing users to define inputs and expectations in CSV and JSON files
- Integration with the Jasmine framework, allowing developers to run tests in VSCE and Studio Release Management as they would regular JavaScript tests
- Provides insights into Canonical & Source test results, including errors thrown by the DI engine
Tests can be authored in five simple steps. For more details, see the Writing Tests section.
Writing Tests
Step 1: Set Up Data Integration
Create data Types and metadata for data integration within your package, ensuring that all Canonical, Source, Transform, and target Types are properly configured.
Step 2: Create Test Folder Structure
Create a canonical/<canonical-or-source-name>/ directory under the test/ directory for each Canonical or Source Type you would like to test.
Note: The directory containing expected values can be configured by setting CanonicalTester.Config#pathToCanonicalDir.
├── src/
└── test/
└── canonical/
├── CanonicalTypeOne
├── CanonicalTypeTwo
├── SourceExample
└── ...Step 3: Define Inputs
For each Canonical or Source Type, create an input/ directory containing a CSV or JSON file of input values. These files must include seed-like data to be ingested through the DI pipeline. Example:
Note: The directory containing expected values can be configured by setting CanonicalTester.Config#inputDirName.
├── src/
└── test/
└── canonical/
├── CanonicalTypeOne/
│ └── input/
│ └── values.csv <-- Step 3: Define input values.
├── CanonicalTypeTwo/
│ └── input/
│ └── values.json <-- Step 3: Define input values. Can also be in JSON format.
├── SourceExample/
│ └── input/
│ └── values.csv <-- Step 3: Define input values.
└── ...Step 4: Define Expectations
Each Canonical or Source Type can produce one or more target Types based on the defined transforms for those Types. To compare the transformed values with the expected values, create folders for each target Type within the expected/ directory.
Note: The directory containing expected values can be configured by setting CanonicalTester.Config#expectedDirName.
Canonical Expectation File Structure Example
├── src/
└── test/
└── canonical/
├── ...
├── CanonicalTypeOne/
│ ├── input/
│ │ └── values.csv
│ └── expected/
│ ├── TargetTypeOne/
│ │ └── values.csv <-- Step 4: Define expectation.
│ └── TargetTypeTwo/
│ └── values.json <-- Step 4: Define expectation. Can also be in JSON format.
└── ...Source Expectation File Structure Example
├── src/
└── test/
└── canonical/
├── ...
├── SourceExample/
│ ├── input/
│ │ └── values.csv
│ └── expected/
│ ├── CanonicalExample/
│ │ └── values.csv <-- Step 4: Define expectation.
│ └── SourceTarget/
│ └── values.csv <-- Step 4: Define expectation.
└── ...Step 5: Author Tests
Once the test data structure is set up, create a .js test file in your package's /test/js-rhino folder. The .js must call BaseCanonicalTester.runCanonicalTests().
By default, tests will be run for all Canonical and Source Types in the package. A BaseCanonicalTester.Spec can optionally be passed in to modify the behavior of tests - such as specifying target types or disabling.
Please note that canonical tests for Types stored in a key-value database like Cassandra can't be run with a targetSpec specifying partition information. Not specifying a spec in packages that include key-value Types will result in a critical error.
Template Canonical Tester Test
var filename = '<test-file-name>.js';
BaseCanonicalTester.runCanonicalTests({
// BaseCanonicalTester.Spec
});The following customizations can be made to a canonical test:
- Skipping Canonical Types: Use
BaseCanonicalTester.Spec#canonicalTypeSpecsto specify thecanonicalTypeand setdisabled: true. - Skipping Source Types: Use
BaseCanonicalTester.Spec#sourceTypeSpecsto specify thesourceTypeand setdisabled: true. - Customizing Target Type Tests: Configure
BaseCanonicalTester.CanonicalTypeSpec#targetTypeSpecsto tailor tests for specific target Types.
Example
The following is an example test.
- Tests for the
CanonicalTypeTwo&SourceExampleare disabled CanonicalTypeOneis tested for two target Types:TargetTypeTwo, where the test is disabledTargetTypeTwo, where the comparison key field is customized
var filename = 'test_mytest.js';
BaseCanonicalTester.runCanonicalTests({
name: filename,
sourceTypeSpecs: [
{
sourceType: 'SourceExample',
disabled: true,
},
],
canonicalTypeSpecs: [
{
canonicalType: 'CanonicalTypeOne',
targetTypeSpecs: [
{
targetType: 'TargetTypeOne',
disabled: true,
},
{
targetType: 'TargetTypeTwo',
comparisonKeyFields: ['parent.id', 'start'],
},
],
},
{
canonicalType: 'CanonicalTypeTwo',
disabled: true,
},
],
});Running Tests
Canonical Tester runs tests using the Jasmine framework. This means tests can be run either in Release Management as part of your application tests, or in the C3 AI VS Code Extension.
Debugging Tests
The Canonical Tester constructs and executes canonical tests using a dynamically generated Jasmine tree. The resulting error messages and test results are limited to the outcome of the expect statements within each it block. Since Jasmine handles assertion failures internally, errors/failures output by the tests are inherently concise.
To obtain detailed results, canonical tests can be executed in the static console. The resulting output can be inspected through the BaseCanonicalTesterResults object returned by the following API:
BaseCanonicalTester.testAllCanonicals();Customizing Test Paths
The Canonical Tester uses package-level configurations defined in the CanonicalTester.Config Type to determine the locations of all canonical tests.These configurations can be customized by modifying the configuration file at <package>/config/BaseCanonicalTester.Config/BaseCanonicalTester.Config.json.
Configuration Options:
- pathToCanonicalDir: Defines the base directory for canonical tests (default:
/test/canonical/). - inputDirName: Specifies the folder name for input data (default:
input). - expectedDirName: Specifies the folder name for expected results (default:
expected).
Example configuration
{
"pathToCanonicalDir": "/test/custom/canonical/",
"inputDirName": "customInput",
"expectedDirName": "customExpected"
}Key C3 AI Types in this package
| C3 AI Type | Description |
|---|---|
| BaseCanonicalTester | A Type that tests canonicals using the Jasmine framework |
| BaseCanonicalTester.CanonicalTypeSpec | The spec that describes how to run a test for a canonical Type |
| BaseCanonicalTester.SourceTypeSpec | The spec that describes how to run a test for a source Type |
| BaseCanonicalTester.Spec | The spec that describes how a canonical test should be run |
| BaseCanonicalTester.TargetTypeSpec | The spec that describes how to run a test for a target Type |
| BaseCanonicalTester.TypeKind | Enum Type fields used to define Canonical or Source value Types |
| BaseCanonicalTesterResults | Test result produced |