C3 AI Documentation Home

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.

Text
├── 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.

Text
├── 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

Text
├── 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

Text
├── 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

JavaScript
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#canonicalTypeSpecs to specify the canonicalType and set disabled: true.
  • Skipping Source Types: Use BaseCanonicalTester.Spec#sourceTypeSpecs to specify the sourceType and set disabled: true.
  • Customizing Target Type Tests: Configure BaseCanonicalTester.CanonicalTypeSpec#targetTypeSpecs to tailor tests for specific target Types.

Example

The following is an example test.

  • Tests for the CanonicalTypeTwo & SourceExample are disabled
  • CanonicalTypeOne is tested for two target Types:
    • TargetTypeTwo, where the test is disabled
    • TargetTypeTwo, where the comparison key field is customized
JavaScript
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:

JavaScript
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

JSON
{
  "pathToCanonicalDir": "/test/custom/canonical/",
  "inputDirName": "customInput",
  "expectedDirName": "customExpected"
}

Key C3 AI Types in this package

C3 AI TypeDescription
BaseCanonicalTesterA Type that tests canonicals using the Jasmine framework
BaseCanonicalTester.CanonicalTypeSpecThe spec that describes how to run a test for a canonical Type
BaseCanonicalTester.SourceTypeSpecThe spec that describes how to run a test for a source Type
BaseCanonicalTester.SpecThe spec that describes how a canonical test should be run
BaseCanonicalTester.TargetTypeSpecThe spec that describes how to run a test for a target Type
BaseCanonicalTester.TypeKindEnum Type fields used to define Canonical or Source value Types
BaseCanonicalTesterResultsTest result produced

Package-Level Changelogs

Was this page helpful?