Cucumber CLI Main skipping the feature files - cucumber

I want to execute cucumber tests from cucumber CLI instead of Maven.
I have below code in my Runner class:
import io.cucumber.core.cli.Main;
public class Runner {
public static void main(String[] args) {
Main.main(new String[]{"-g", "src/test/java/com/company/project/stepdefinitions", "-t", "Regression", "src/test/resources/features"});
}
}
When I execute it, it doesn't run any tests -
0 Scenarios
0 Steps
0m0.163s
Any Idea what am I missing ? If I remove the tag then it detects the feature file but says corresponding stepdefinition is missing.
Main.main(new String[]{"-g", "src/test/java/com/company/project/stepdefinitions/module1/Stepmodule1","src/test/resources/features/module1/ValidateModule1.feature"});
Undefined scenarios:
file:///C:/Users/.../src/test/resources/features/module1/ValidateModule1.feature:5 # To Test Module1
1 Scenarios (1 undefined)
1 Steps (1 undefined)
0m0.228s
Am I calling main function in CLI with wrong parameters?
Kind Regards,
Abhi

Thanks for the suggestions.
The below syntax worked for me for giving glue and feature files in a standalone Java class.
import io.cucumber.core.cli.Main;
public class Runner {
public static void main(String[] args) {
Main.main(new String[]{"-g", "com.company.project.stepdefinitions","-t", "#Regression","-p", "com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:", "src/main/resources/features/"});
}
}

Related

How to get Runner class inside cucumber event handler

I need to define a custom annotations in cucumber runner class. I have a event handler class where i get a callback when a test case is finished/started etc.
The issue i am facing is i am not able to get the runner class inside the event handler class, and hence i am unable to read the custom annotations applied in the runner class.
Is there a way for that in cucumber.
Eg. in junit , i can get the custom annotation applied in the test class as :
public void testFinished(Description description) { description.getTestClass();} from where i could read my annotation.
in testng, itestContext.getTestClass().getRealClass();.
Any help would be highly appreciated.
Many thanks in advance.
Eg. i need to read the annotations here,
private EventHandler<TestCaseFinished> caseFinishedEventHandler = new EventHandler<TestCaseFinished>() {
#Override
public void receive(TestCaseFinished event) {
//Read annotations here...
}
}; /*Or here*/ private EventHandler<TestRunFinished> runFinishedEventHandler = new EventHandler<TestRunFinished>() {
#Override
public void receive(TestRunFinished event) {
}
};
Solved this issue by :
For Junit : Extending Cucumber runner class. class argument of the constructor returns the runner class where custom annotations are present.
For TestNG : Extending AbstractTestNGCucumberTests in case of TestNG. this.getClass() returns the runner class where custom annotations are present.

How can I run code in JUnit before Spring starts?

How can I run code in my #RunWith(SpringRunner.class) #SpringBootTest(classes = {...}) JUnit test before Spring starts?
This question has been asked several times (e.g. 1, 2) but was always "solved" by some configuration recommendation or other, never with a universal answer. Kindly don't question what I am about to do in that code but simply suggest a clean way to do it.
Tried so far and failed:
Extend SpringJUnit4ClassRunner to get a class whose constructor can run custom code before initializing Spring. Failed because super(testClass) must be called first thing and already does a whole lot of things that get in the way.
Extend Runner to get a class that delegates to SpringRunner instead of inheriting it. This class could run custom code in its constructor before actually instantiating the SpringRunner. However, this setup fails with obscure error messages like java.lang.NoClassDefFoundError: javax/servlet/SessionCookieConfig. "Obscure" because my test has no web config and thus shouldn't meddle with sessions and cookies.
Adding an ApplicationContextInitializer that is triggered before Spring loads its context. These things are easy to add to the actual #SpringApplication, but hard to add in Junit. They are also quite late in the process, and a lot of Spring has already started.
One way to do it is to leave out SpringRunner and use the equivalent combination of SpringClassRule and SpringMethodRule instead. Then you can wrap the SpringClassRule and do your stuff before it kicks in:
public class SomeSpringTest {
#ClassRule
public static final TestRule TestRule = new TestRule() {
private final SpringClassRule springClassRule =
new SpringClassRule();
#Override
public Statement apply(Statement statement, Description description) {
System.out.println("Before everything Spring does");
return springClassRule.apply(statement, description);
}
};
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
#Test
public void test() {
// ...
}
}
(Tested with 5.1.4.RELEASE Spring verison)
I don't think you can get more "before" than that. As for other options you could also check out #BootstrapWith and #TestExecutionListeners annotations.
Complementing jannis' comment on the question, the option to create an alternative JUnit runner and let it delegate to the SpringRunner does work:
public class AlternativeSpringRunner extends Runner {
private SpringRunner springRunner;
public AlternativeSpringRunner(Class testClass) {
doSomethingBeforeSpringStarts();
springRunner = new SpringRunner(testClass);
}
private doSomethingBeforeSpringStarts() {
// whatever
}
public Description getDescription() {
return springRunner.getDescription();
}
public void run(RunNotifier notifier) {
springRunner.run(notifier);
}
}
Being based on spring-test 4.3.9.RELEASE, I had to override spring-core and spring-tx, plus javax.servlet's servlet-api with higher versions to make this work.

How to use multiple classes in multiple files in scripts?

I need to make a standalone Groovy script that does not require compilation and runs without Groovy installed. It works well, but it fails to recognize any other script than the main script.
My folder structure is the following:
libs\
groovy-all-2.4.3.jar
ivy-2.4.0.jar
src\
makeRelease.groovy
ReleaseHelper.groovy
I am launching the script this way from the src folder:
java -cp "../libs/*" makeRelease.groovy
makeRelease looks like this:
public class makeRelease {
public static void main(String... args) {
new ReleaseHelper()
...
}
}
When run this is the output:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
src\makeRelease.groovy: 5: unable to resolve class ReleaseHelper
How can I include other classes (that reside in separate files) in such portable scripts?
I think that it is easier than you think:
libs\
groovy-all-2.4.3.jar
src\
main.groovy
Greeter.groovy
Where main.groovy
public class Main {
public static void main(args) {
println 'Main script starting...'
def greeter = new Greeter()
greeter.sayHello()
}
}
and Greeter.groovy
class Greeter {
def sayHello() {
println 'Hello!'
}
}
Simply add to the classpath the folders where you have the classes in separate files:
java -cp .;..\libs\groovy-all-2.4.3.jar groovy.ui.GroovyMain main.groovy
The above yields:
Main script starting...
Hello!

How to use import inside a dynamically loaded groovy file

I am trying to come up with a way for my users to supply plugins into the main groovy application by dynamically loading their source file. But their groovy file contains import statements and I don't know how to make them work even with an apparently good classpath.
The main application is a shell script, bin/top.sh:
#!/bin/bash
groovy-2.4.1/bin/groovy -cp lib lib/Top.groovy
The lib/Top.groovy class:
public class Top {
public static void main(String[] args) {
ClassLoader parent = getClass().getClassLoader()
GroovyClassLoader loader = new GroovyClassLoader(parent)
Class groovyClass = loader.parseClass(new File("UserPlugin.groovy"))
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance()
groovyObject.invokeMethod("run",args)
}
}
The user class UserPlugin.groovy:
// The following import can be found in the classpath
// passed by the shell script (under lib/, next to Top.groovy)
import Lib
class UserPlugin {
def UserPlugin() {
Lib lib = new Lib()
}
def run(String [] args) {
println("Running with: "+args)
}
}
And the lib/Lib.groovy:
class Lib {
def Lib() {
println("Lib")
}
}
When I run with bin/top.sh, I get: UserPlugin.groovy: 3: unable to resolve class Lib
When I add lib to the class loader like so loader.addClasspath('lib'), it's rather catastrophic:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
java.lang.RuntimeException: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
at org.codehaus.groovy.control.CompilationUnit.convertUncaughtExceptionToCompilationError(CompilationUnit.java:1088)
How can this work while keeping it all scripted and not compiled? Is this even possible?
Sorry I don't have time to find the bug but I think the problem is with the setting of the context classloader. GroovyShell.run takes care of that for you which I recommend over replicating that code.
Top.groovy
public class Top {
public static void main(String[] args) {
new GroovyShell().run(new File("UserPlugin.groovy"), args)
}
}
If you're willing to make Top.groovy a script rather than class then you can do this:
Top.groovy
run(new File("UserPlugin.groovy"), args)
The UserPlugin.groovy then needs to be either a class (with a main method) or a script to use the standard Groovy calling logic.

How to properly quit WebDriver after completing all UI tests with Cucumber

We are using Selenium WebDriver to do UI testing, along with Cucumber. The language is Groovy, and the build tool is Gradle. Because it is expensive to create a WebDriver instance, we want to instantiate only one WebDriver instance and use it through all tests. However, we are having trouble to quit the driver properly after all tests are completed. Namely, the browser process spawned during the tests is still alive after running all the tests.
The code is currently structured like below.
// Test base class
class UITestBase {
WebDriver driver
static {
init()
}
static void init() {
// instantiate a webdriver
}
}
// Entry class of cucumber run
RunWith( Cucumber )
Cucumber.Options(...)
class CukeRunEntry {}
// Cucumber step class
class WhenSteps extends UITestBase {
#When(/^something happens$/)
void something_happens() {
// step implmentation
}
}
So, how can I call driver.quit() after all tests are finished but before gradle finishes the test task (we run the tests with ./gradlew test from command line)? I tried overriding the finalize() method, but that didn't help.
Thank you very much.
If I were you, I would prefer using SharedDriver that you can find here => https://github.com/cucumber/cucumber-jvm/blob/master/examples/java-webbit-websockets-selenium/src/test/java/cucumber/examples/java/websockets/SharedDriver.java
It makes life easier.
Edit
If you don't wish to use SharedDriver, you can add a block like below to the UITestBase class as illustrated in the question:
private static final Thread CLOSE_THREAD = new Thread() {
#Override
public void run() {
try {
driver.quit()
} catch ( Exception e ) {
}
}
}
static {
init()
Runtime.getRuntime().addShutdownHook(CLOSE_THREAD)
}
The above code is essentially what's used in SharedDriver to ensure safe close of the WebDriver instance.

Resources