This document describes the high level architecture of bespin.
CLI
|-> Config ----`config`----> Runtime
|-> Components |-> Locate Test Files (TestFileLocator)
| - TestFileLocator |-> Parse Out Tests (TestFileParser)
| - TestFileParser |-> Run Tests (Runner)
| - Runner |-> Report Results (Reporter/s)
| - Reporter/s
|-> Settings
|-> Globals
The CLI is main consumer entry point for the framework. It's responsible for loading a Config
, initializing the Runtime
and reporting results to the terminal using it's own reporter.
The Runtime
contains all the frameworks core logic and is used by consumer implementations (e.g. cli). The run
method envokes the runtime and returns an array of TestResult
.
import { Config, Runtime } from "@testingrequired/bespin-core";
const config = await Config.load("bespin.config.js");
const runtime = new Runtime(config);
const results = await runtime.run();
The Config
is where the framework's behavior is defined. It's used by the Runtime
to drive that behavior.
A javascript file exporting a config. Used by the cli during execution.
const { Config } = require("@testingrequired/bespin-core");
module.exports = new Config(__filename);
The Config
constructor requires __filename
to be passed to have a reference to it's own location.
Components for locating, parsing, running and reporting are set here.
const { Config } = require("@testingrequired/bespin-core");
module.exports = new Config(__filename)
.withLocator(new SomeLocator())
.withParser(new SomeParser())
.withRunner(new SomeRunner())
.withReporter(new SomeReporter())
.withReporter(new AnotherReporter());
Settings affect core framework functionality.
const { Config } = require("@testingrequired/bespin-core");
module.exports = new Config(__filename)
.withSetting("randomizeTests", true)
.withSettings({
testFileFilter: "",
testNameFilter: "",
});
interface Settings {
randomizeTests?: boolean;
testFileFilter?: string;
testNameFilter?: string;
}
Globals registered are exposed to test functions at runtime.
const { Config } = require("@testingrequired/bespin-core");
const someLib = require("someLib");
module.exports = new Config(__filename).withGlobal("someLib", someLib);
A config file can be loaded from a path.
import { Config } from "@testingrequired/bespin-core";
const config = await Config.load("bespin.config.js");
A ValidConfig
is a Config
with TestFileLocator
, TestFileParser
and Runner
set.
import { Config } from "@testingrequired/bespin-core";
const config = new Config()
.withLocator(new SomeLocator())
.withParser(new SomeParser())
.withRunner(new SomeRunner());
if (Config.isValid(config)) {
// config is a ValidConfig in this if block
}
An error will be thrown if the loaded config is not valid.
There are four types of components that can be configured: TestFileLocator
, TestFileParser
, Runner
, & Reporter
.
This component locates test files and returns an array of their paths.
This component parses a test file for tests.
The getTests
method accepts a test file path and returns an array of TestInTestFile
which has two properties: testFilePath
and testName
. This method also accepts a Record<string, any>
of global variables exposed to test functions. These globals are configured on the Config
.
interface TestInTestFile {
public readonly testFilePath: string;
public readonly testName: string;
public readonly testFn: TestFunction;
}
type TestFunction = () => Promise<void>;
This component accepts an array of TestInTestFile
, runs them using the TestExecutor
and returns an array of corresponding TestResult
.
The TestExecutor
is a core framework function that accepts a TestFunction
and returns a TestResult
.
interface TestResult {
state: TestResultState;
time: number;
error?: Error;
message?: string;
}
enum TestResultState {
PASS = "PASS",
FAIL = "FAIL",
ERROR = "ERROR",
}
One or more reporters can be registered to the config. They expose the following methods to implement reporting: onRunStart
, onTestStart
, onTestEnd
, onRunEnd
.
A Plugin
is (currently) simply a class that is passed a Config
in to it's constructor. This allows the plugin to configure components, settings and globals.