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.