prashant-ramcharan / courgette-jvm

Multiprocess | Parallel Cucumber-JVM | Parallelize your Java Cucumber tests on a feature level or on a scenario level.
MIT License
131 stars 38 forks source link

Cucumber Test runner initialization error #309

Closed Tash2610 closed 2 years ago

Tash2610 commented 2 years ago

Hi,

I'm getting below error when running my test runner class, could you please help on the issue:-

java.io.IOException: Cannot run program "java": CreateProcess error=206, The filename or extension is too long at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048) at courgette.runtime.CourgetteFeatureRunner.run(CourgetteFeatureRunner.java:32) at courgette.runtime.CourgetteRunner.runFeature(CourgetteRunner.java:236) at courgette.runtime.CourgetteRunner.lambda$run$3(CourgetteRunner.java:85) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.io.IOException: CreateProcess error=206, The filename or extension is too long at java.lang.ProcessImpl.create(Native Method) at java.lang.ProcessImpl.(ProcessImpl.java:453) at java.lang.ProcessImpl.start(ProcessImpl.java:139) at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029) ... 7 more

Below is my test runner class:- import java.io.File; import java.io.IOException;

import org.junit.runner.RunWith;

import courgette.api.CourgetteBeforeAll; import courgette.api.CourgetteOptions; import courgette.api.junit.Courgette; import courgette.api.CourgetteRunLevel; import courgette.api.CucumberOptions;

@RunWith(Courgette.class) @CourgetteOptions( threads = 10, runLevel = CourgetteRunLevel.FEATURE, cucumberOptions = @CucumberOptions(plugin = { "summary", "json:target/cucumber.json", "pretty:target/cucumber-pretty.txt", "junit:target/cucumber-results.xml" , "html:target/cucumber-html-report/cucumber.html" }, glue = { "com.optum.cams.stepDefinitions" }, features = { "src/main/resources/features" }, monochrome = true, tags = "@Smoke_Test")) public class CucumberRunnerTest {

@CourgetteBeforeAll
public static void setupproperty() throws IOException {

    // to set browser
    System.setProperty("BrowserType", "edge");
    //System.setProperty("BrowserEnv", "saucelab");

} }

prashant-ramcharan commented 2 years ago

Hi,

Your classpath exceeds the 32k Windows limit. You can use the classPath Courgette option to workaround this limitation.

See example here: https://github.com/prashant-ramcharan/courgette-jvm-classpath-example

Tash2610 commented 2 years ago

I have added classPath = {"target/libs/", "target/classes/"} to my runner class. target/libs/ contains all the directories with dependencies JARs and target/classes/ contains all the framework classes. But now I'm getting below error:-

courgette.runtime.CourgetteTestErrorException: There were errors when running the test. Refer to the console for more information.

prashant-ramcharan commented 2 years ago

Can you try this in your Courgette runner ?

classPath = {"target/libs/*", "target/test-classes/"},

Are you using Maven or Gradle and can you paste the console output showing the error ?

Tash2610 commented 2 years ago

I'm using Maven and added mentioned classPath but still getting below error:-

java.io.IOException: Cannot run program "java": CreateProcess error=206, The filename or extension is too long at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048) at courgette.runtime.CourgetteFeatureRunner.run(CourgetteFeatureRunner.java:32) at courgette.runtime.CourgetteRunner.runFeature(CourgetteRunner.java:236) at courgette.runtime.CourgetteRunner.lambda$run$3(CourgetteRunner.java:85) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.io.IOException: CreateProcess error=206, The filename or extension is too long at java.lang.ProcessImpl.create(Native Method) at java.lang.ProcessImpl.(ProcessImpl.java:453) at java.lang.ProcessImpl.start(ProcessImpl.java:139) at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029) ... 7 more

Tash2610 commented 2 years ago

Hi,

I'm able to execute Courgette runner successfully on Jenkins without adding classpath in runner class. Thanks for creating Courgette-JVM.

But earlier I was using -Dcucumber.filter.tags="$tagsToRun" to replace tags during runtime in jenkins. But now when I'm providing tags through jenkins it's not working, is there any change I need to make in maven goal?

Maven Goal:- mvn clean integration-test -Dcucumber.filter.tags="$tagsToRun" Runner Class:- tags = "@Smoke_Test or @Regression_Test"

Also, running through my suite through jenkins only covers half of my requirement, I also want to run Courgette runner on my local machine but even with using "classPath = {"target/libs/*", "target/test-classes/"}," getting above mentioned error, it would be helpful if you can help more on this error.

prashant-ramcharan commented 2 years ago

Hello,

You should pass tags to your Courgette runner using: -Dcucumber.tags

mvn clean integration-test -Dcucumber.tags="@Smoke_Test or @Regression_Test"

The CreateProcess error is only an issue on Windows operating systems.

You should not see this issue if you use the Courgette classPath workaround but I'm unable provide any further support without actually seeing your project or environment.

Does the Courgette example project run fine on your machine? https://github.com/prashant-ramcharan/courgette-jvm-maven-example

For further support, please provide an example project to replicate this.

Tash2610 commented 2 years ago

Hi Again,

One more question I have after doing the parallel execution, in my framework there are multiple Input and Output CSV files and each scenarios requires to read and write data in the CSV files.

Now, when doing the execution through jenkins all the feature files are running in parallel but I'm seeing lots of concurrency issues while reading and writing data on the CSV files. As my framework is not threadsafe, I was assuming that using courgette-jvm each feature file will have different instances or JVMs on which they will run like multiple sessions with there own set of files.

But it seems like all the parallel execution are accessing same set of files across different feature files. Is there any way using courgette-jvm through which I can remove these concurrency issues so that each feature file has its own session and set of files?

prashant-ramcharan commented 2 years ago

Courgette runs each feature / scenario in a separate JVM so you cannot share resources across these JVMs.

You should ensure your tests are not dependant on state or resources (i.e. should not depend on input from a shared CSV file) as this will not work well with Courgette or parallel execution.

Your framework needs to be able to run each feature / scenario without having to depend on something external (shared) to setup each test.

You can use @CourgetteBeforeAll and @CourgetteAfterAll hooks to run tasks before and after Courgette runs the tests but fundamentally you need your framework to be independent on shared state and each test should pass in its own right.

Tash2610 commented 2 years ago

So you mean, like my framework has multiple CSV files what courgette will do is create separate JVMs for each feature/scenario but all the CSV files(resources) will remain common across separate JVMs and each JVMs will try to access common set of files. Is my understanding correct?

prashant-ramcharan commented 2 years ago

Yes, that's correct.

Tash2610 commented 2 years ago

So if I make framework changes such that instead of reading data from CSV or excel file if it read data from like properties files then each JVM will have its own set of properties files and these concurrency issues will not occur? Or I can make read and write class a more threadsafe class? Will my approach works fine with courgette?

prashant-ramcharan commented 2 years ago

Creating a thread safe class will only be thread safe for a single test / JVM as each test is run in a separate JVM.

For your tests to work fine with Courgette you need to ensure your Cucumber tests can run without dependancies on shared resources whether it's properties files, text files, excel docs etc..

The general principle is if each Cucumber test can be run independently, Courgette will be able to run your Cucumber tests in parallel without concurrency issues.

Writing deterministic tests where test inputs are known beforehand would be best. Perhaps you can make use of Cucumber data tables or scenario outline for your scenarios instead of sourcing data from excel docs...just a thought!

prashant-ramcharan commented 2 years ago

Back to this issue, if you still experiencing problems please share a project I can use to replicate this error.

prashant-ramcharan commented 2 years ago

@Rahul-2627 please re-open this issue if required.