I want to run the same Cucumber tests in multiple threads. More specifically, I have a set of features, and running these features in one thread works fine. I use the JSON formatter to record running time of each step. Now I want to do load test. I care more about the running time of each feature/step in a multi-thread environment. So I create multiple threads, and each thread runs on the same feature set. Each thread has its own JSON report. Is this possible in theory?
For some project setup reason I cannot use the JUnit runner. So I have to resort to the CLI-way:
long threadId = Thread.currentThread().getId();
String jsonFilename = String.format("json:run/cucumber%d.json", threadId);
String argv[] = new String[]{
"--glue",
"com.some.package",
"--format",
jsonFilename,
"d:\\features"};
// Do not call Main.run() directly. It has a System.exit() call at the end.
// Main.run(argv, Thread.currentThread().getContextClassLoader());
// Copied the same code from Main.run().
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
RuntimeOptions runtimeOptions = new RuntimeOptions(new Env("cucumber-jvm"), argv);
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
Runtime runtime = new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
runtime.writeStepdefsJson();
runtime.run();
I tried to create a seperate thread for each Cucumber run. The problem is, only one of the thread has a valid JSON report. All the other threads just create empty JSON files. Is this by design in Cucumber or is there something I missed?
Well if you can find a way for cucumber to output scenario location ( I.e. feature_file_path:line_nunber_in_feature_file) for all the scenarios you want run based on given tag, then you can use gpars and gradle to run scenarios in parallel. Step 1: In the first gradle task, we’ll use above solution to generate a text file (say scenarios.txt) containing locations for all the scenarios that we want to execute Step 2: Next, extract contents of scenarios.txt generated in step 1 into a groovy list say scenariosList Step 3: create one more task (javaExec), here we’ll use gpars withPool in combination with scenariosList.eachParallel, and use cucumber main class and other cucumberOptions to run these scenarios in parallel. PS: here we will provide a scenario location as the value of the option “features” so that cucumber will run only this scenario. Also no need to provide any tag name as we already have a list of scenarios that we need to execute.
Note: You need to use a machine with high configuration like a Linux sever because a new jvm instance is created per scenario, and probably use a cloud service like Saucelabs to execute scenarios. This way you don’t have to worry about the infrastructure.
Step4: This is the last step. Every scenario bran in step 3 will generate an json output file. You have to collate the output based on the feature names so as to generate one json file per feature file.
This solution sounds a bit complex, but with right efforts can yield significant results.