Hello
How are we expected to pass a parameter to the Mocha instance we are starting programatically, without using environment variables?
In my case I have a long number of environments specified by a number (30, 31, 32, etc.) and I would like to pass a number to my Mocha test, so that I can read that environments specific config file.
Any best pratices or ways of accomplishing this?
Thanks!
Could you supply more details on the setup (just basic details) of these environments and how they run mocha.
Mocha doesn't have anything that allows you to pass "parameters" into test files, suites, hooks, nor tests.
If you need to do this, I'd suggest pulling in something like dotenv and using Mocha's --require to require a custom test harness file, which will then load the proper config.
How are we expected to pass a parameter to the Mocha instance we are starting programatically, without using environment variables?
Why _wouldn't_ you use environment variables?
If you need to do this, I'd suggest pulling in something like dotenv and using Mocha's
--requireto require a custom test harness file, which will then load the proper config.
How would I require a specific file when starting Mocha programatically using --require?
@simonsen78 yes. You can specify multiple --require files . Note file import order is earliest-first.
No response of hesitation with environment variable...
Assuming:
"test/setup_env.js"
const path = require('path');
const env = process.env.FOO_CONF;
if (!env) {
throw new Error('"FOO_CONF" not found in environment');
}
const conffile = env + '.conf.json';
const confpath = path.join(__dirname, 'conf', conffile);
console.log('loading "' + confpath + '"');
const config = require(confpath);
Run
$ FOO_CONF="35" mocha --file 'test/setup_env.js' 'test/**/*.spec.js'
@plroebuck
Why _wouldn't_ you use environment variables?
I'm not running my test on the actual environment. I'm running them from a server and targeting the different environments. So it feels "wrong" to use an environment variable in this case.
I use the number of the environment in my Mocha code to build target urls for API endpoints and browser URLs.
Also I'm starting the tests in parallel, so I'm not sure if it's "safe" to run a lot of tests in parallel using env variables to configure the tests. My fear (being unsure in the matter) would be that the different Mocha instances would be using the latest value of the env variable? I would feel better/safer passing a number to Mocha and being able to access that in the process, if that makes any sense?
@craigtaub I'm not starting Mocha from the command line, I'm running it programatically using mocha.run(). Not sure you can --require files when doing it like that.
@simonsen78 ah right nope you cant (typical use is to import/setup before invoking mocha) and mocha doesn't have anything that allows you to pass params.
Wonder if something like https://www.npmjs.com/package/continuation-local-storage could help you set and persist variables per test process, not sure.
@plroebuck
Why _wouldn't_ you use environment variables?
I'm not running my test on the actual environment. I'm running them from a server and targeting
the different environments. So it feels "wrong" to use an environment variable in this case.
You realize this is how it's done on pretty much _every_ CI environment (e.g., Travis, AppVeyor, Jenkins), right?. You use env vars to setup your jobs.
I use the number of the environment in my Mocha code to build target URLs for API endpoints
and browser URLs.
A la RAML.
Also I'm starting the tests in parallel, so I'm not sure if it's "safe" to run a lot of tests in parallel
using env variables to configure the tests. My fear (being unsure in the matter) would be that the
different Mocha instances would be using the latest value of the env variable? I would feel
better/safer passing a number to Mocha and being able to access that in the process, if that
makes any sense?
Starting the tests in parallel - you mean like this?:
#!/bin/bash
mkdir output
for i in 1 2 3 4 5
do
echo "Launching environment job $i"
setup="test/setup_env.js"
outfile="output/results-${i}.xunit.xml"
reporterOptions="--reporter-options output=${outfile}"
reporter="--reporter xunit"
FOO_CONF=${i} mocha ${reporter} ${reporterOptions} --file ${setup} 'test/**/*.spec.js' &
done
Every job will have its own environment with the value of FOO_CONF at the time it was launched.
You realize this is how it's done on pretty much _every_ CI environment (e.g., Travis, AppVeyor, Jenkins), right?. You use env vars to setup your jobs.
I realize that. But I'm not a part of the CI process. Not yet anyway. Merely testing stuff from afar. API and front end mostly.
A la RAML.
Not sure how that applies here?
Starting the tests in parallel - you mean like this?:
...
Every job will have its own environment with the value ofFOO_CONFat the time it was launched.
Should mention that I have integrated Mocha in a FeathersJS + VueJS setup, and tests are run from the server code. That's what I mean when I say "programatically", like it's shown in the wiki using the API/library and mocha.run. So it's reading some "jobs" from a Mongo database, and then looping over them and starting a process for each job, like say max four at a time.
Just accomplished what I was trying to do with Jest actually. Their library has a runCLI method that takes a JSON object with settings, and there you can specify some globals that are passed on to the test process.
So something like this (sorry, writing this from memory):
const jest = require('jest');
defaults = {} // forgot what the import code for default object is here
defaults.globals = {
environmentNumber: 26
}
jest.runCLI(defaults, someOtherObject)
.then( results => {
// do something with the result here
}
}
This is what I wished Mocha has. Because otherwise I'm afraid it's not really usable for my (admittedly very specific) usecase.
I have exactly the same issue with mocha at this moment. I want to run mocha "programmatically" which works fine with hardcoded values. But I want to be able to pass some variables to that process.
Could do this by creating a folder for it in every run and load a dotenv file but that will be an issue when the amount of runs are high (which will happen).
Was thinking of setting a global variable but I'm not sure if mocha.run will be able to access those global variables and this will also force me into running it in a synchronous way.
Anyone has an idea on how to pass some variable (string) without having to create lot of folders, softlinks etc like I would have to when passing the environment variables?
@bramevo you can create a script, e.g., foo.js, and run Mocha with --file foo.js. foo.js will be loaded first, and you can assign to global there.
// foo.js
someAsyncFunction().then((result) => {
global.foo = result.bar;
describe( /* whatever */);
run();
});
Use mocha --delay --file foo.js <other tests>. You can also set the delay and file options within a .mocharc.js.
@bramevo you can create a script, e.g.,
foo.js, and run Mocha with--file foo.js.foo.jswill be loaded first, and you can assign toglobalthere.// foo.js someAsyncFunction().then((result) => { global.foo = result.bar; describe( /* whatever */); run(); });Use
mocha --delay --file foo.js <other tests>. You can also set thedelayandfileoptions within a.mocharc.js.
How would this work when running programmatically? Like described on: https://github.com/mochajs/mocha/wiki/Using-Mocha-programmatically
If somehow I would be able to pass an object through via the Runner class and get that information back in the specs file, that would solve the issue.
When looking into the documentation it seems mocha was never designed to work programmatically.
That is very simple. As run function of Mocha instance, executes the tests in the same process and Nodejs context, you could pass the parameters through a global variable.
File handling Mocha programmatic interface:
import Mocha from 'mocha' // Mocha -Programmatic rest runner https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically
function runMochaTests(additionalParameters) {
global.additionalParameters = additionalParameters
let mocha = new Mocha(mochaOption)
mocha.run(error => console.error)
}
Test file
import assert from 'assert'
let testConfig = global.additionalParameters || {}
console.log(testConfig)
That is very simple. As
runfunction ofMochainstance, executes the tests in the same process and Nodejs context, you could pass the parameters through a global variable.File handling Mocha programmatic interface:
import Mocha from 'mocha' // Mocha -Programmatic rest runner https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically function runMochaTests(additionalParameters) { global.additionalParameters = additionalParameters let mocha = new Mocha(mochaOption) mocha.run(error => console.error) }Test file
import assert from 'assert' let testConfig = global.additionalParameters || {} console.log(testConfig)
This is not elegant, but could work
Most helpful comment
I realize that. But I'm not a part of the CI process. Not yet anyway. Merely testing stuff from afar. API and front end mostly.
Not sure how that applies here?
Should mention that I have integrated Mocha in a FeathersJS + VueJS setup, and tests are run from the server code. That's what I mean when I say "programatically", like it's shown in the wiki using the API/library and mocha.run. So it's reading some "jobs" from a Mongo database, and then looping over them and starting a process for each job, like say max four at a time.
Just accomplished what I was trying to do with Jest actually. Their library has a runCLI method that takes a JSON object with settings, and there you can specify some globals that are passed on to the test process.
So something like this (sorry, writing this from memory):
This is what I wished Mocha has. Because otherwise I'm afraid it's not really usable for my (admittedly very specific) usecase.