Skip to content

Latest commit

 

History

History
 
 

mocha-test-setup

@fluid-internal/mocha-test-setup

IMPORTANT: This package is intended strictly as an implementation detail of the Fluid Framework and is not intended for public consumption. We make no stability guarantees regarding its APIs.

This package has a few main purposes:

  • Expose/generate a default .mocharc.cjs configuration for running mocha tests, which other packages can extend.
  • Map paths for required packages/modules to account for Lerna's dependency hoisting.
  • Add mocha beforeAll, beforeEach and afterEach root hook plugins to add some special behavior when we run tests.

Base mocharc.cjs configuration

To leverage the base mocha configuration exposed by this package, first add it as a devDependency to your package.json (the rest of the file has been omitted):

{
	"devDependencies": {
		"@fluid-internal/mocha-test-setup": "version-that-matches-the-rest-of-the-release-group"
	}
}

Then put this in a .mocharc.cjs file at the root of your package:

"use strict";

const getFluidTestMochaConfig = require("@fluid-internal/mocha-test-setup/mocharc-common");

const packageDir = __dirname;
const config = getFluidTestMochaConfig(packageDir);
module.exports = config;

If you need extra configuration, make changes to the config object before assigning it to module.exports.

Mocha will use this file by default if no path to a configuration file is provided explicitly.

The default configuration generated by getFluidTestMochaConfig() looks like this:

{
  "exit": true,
  "recursive": true,
  "require": ["path1", "path2"], // Mapped paths for packages/modules indicated as required when calling getFluidTestMochaConfig()
  "unhandled-rejections": "strict",
};

The configuration will have additional settings if the following environment variables are present:

FLUID_TEST_TIMEOUT

If it exists, the default configuration will also include this:

{
	"timeout": "<value-of-FLUID_TEST_TIMEOUT>"
}

FLUID_TEST_FORBID_ONLY

If it exists, the default configuration will also include this:

{
	"forbid-only": "true"
}

FLUID_LOGGER_PROPS

In case there is a need to override telemetry metrics, one can make use of an environment variable FLUID_LOGGER_PROPS, that to override them during execution time:

FLUID_LOGGER_PROPS='{ "hostName": "Benchmark" }'

Mapping of package paths to account for Lerna hoisting

The way we use Lerna to manage our monorepo, package dependencies are sometimes moved out of the node_modules folder of the package that declares them, and into a node_modules folder at the root of the release group. This applies to external dependencies (i.e. not between packages in our repo) that are present in more than one of our packages, including mocha itself as well as other test runners, which means that their path when they execute might not be the one you'd normally expect. This can cause issues when test scripts point to other dependencies of the package being tested (e.g. with the -r/--require flag) when running tests. This utility maps the paths of packages/modules passed to the getFluidTestMochaConfig() function, to ensure they are imported from whichever location they end up at.

NOTE: once we move to pnpm this functionality might become irrelevant because pnpm keeps all dependencies in the expected paths and creates the necessary symlinks, instead of changing where dependency folders are located.

Considerations for non-package/module arguments

Sometimes you'll want to provide a package/module/path as an argument when executing your tests but outside of the required packages that you can pass to getFluidTestMochaConfig(). For example, the path to a reporter file:

mocha --require @fluid-internal/mocha-test-setup --reporter @fluid-tools/benchmark/dist/MochaReporter.js

Depending on where that file is coming from, you'll need to be careful with how that path is specified. E.g. @fluid-tools/benchmark, while being part of the repository, is not part of any release group, so it will always be downloaded from the public npm feed and treated as an external dependency. Since several packages declare it as a dependency, Lerna will hoist it to node_modules at the root of the release group. In general, the safest solution is to specify it starting with the package name (including scope if applicable). This might break in a few edge cases as long as we use Lerna with hoisting, so we'll have to deal with them individually.

A particular way of specifying a package/module/path (e.g. starting with the package name vs starting with node_modules/) might behave differently locally and in CI builds, so that's another factor to keep in mind.

Special behavior

Supress console output by default

console.log(), console.warn() and console.error() are disabled by default when using this package. They can be re-enabled by setting the FLUID_TEST_VERBOSE environment variable to any non-empty value, e.g. FLUID_TEST_VERBOSE=1.

Telemetry events

A couple of telemetry events fluid:telemetry:Test_start and fluid:telemetry:Test_end will be generated for each test. The Test_end event includes fields with the test's state (passing/failed), its duration, if it timed out. If a FLUID_TEST_VARIANT environment variable exists, the testVariant field in the events will have its value.

Support for a custom logger

This utility supports using a custom logger implementation. This can be useful to send the operational telemetry generated by the FluidFramework while the tests are running, to a particular log sink.

It is expected that the package with the custom logger implementation adds a getTestLogger() => ITelemetryBufferedLogger function to the global object, which this package will call in order to obtain an instance of the custom logger.

If a custom logger implementation will be used when executing tests in a package that leverages this utility, the path to the module with that implementation should not be specified with the --require/-r flag, but through the FLUID_TEST_LOGGER_PKG_PATH environment variable. This package has logic that needs the custom logger to be imported/executed at a particular time, and we ensure that by requiring that the path be provided through that environment variable.

Contribution Guidelines

There are many ways to contribute to Fluid.

Detailed instructions for working in the repo can be found in the Wiki.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services. Use of these trademarks or logos must follow Microsoft’s Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.

Help

Not finding what you're looking for in this README? Check out fluidframework.com.

Still not finding what you're looking for? Please file an issue.

Thank you!

Trademark

This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.

Use of these trademarks or logos must follow Microsoft's Trademark & Brand Guidelines.

Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.