Is there any way to integrate cucumber with existing testng project? Currently, in our project we are using testng with Page object model. Now we decided to include Cucumber also. But i think we cant , because cucumber uses feature file where we can have 'n' number of scenarios. But testng its running based on #test methods.
So, let me know if we can integrate cucumber + testng and if so, how we can run each and every #test methods using cucumber.
Running cucumber scenarios/features using TestNG runner is possible and it adds value, but reverse is not. What you want to achieve by running TestNG with cucumber runner? If you want to have descriptive step level report with existing TestNG test you can start using QAF.
Yes. You can integrate Cucumber JVM + Test NG.
You can use the Cucumber JVM at the #Test Method of TestNG. Do not use Main.main of the Cucumber API since there's a System.exit(0) at the end. Instead you can use Main.run of the Cucumber.
Call the run method in Test method.
Main.main(new String[]{"-g", "package", "path of feature file"}, ClassLoader.getClassLoader);
The run method requires a classLoader, so generate your own classloader if required.
public static byte run(String[] argv, ClassLoader classLoader) throws IOException {
RuntimeOptions runtimeOptions = new RuntimeOptions(new ArrayList<String>(asList(argv)));
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
Runtime runtime = new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
runtime.run();
return runtime.exitStatus();
}
You can also create your own classLoader to run the main method.
Related
I have test classes wich use other test classes. It is necessary to run these classes depending on the transferred parameter in Jenkins. (For example: if jenkins get parameter testOne then start testsuite testOne. If jenkins get parameter testOther then start testsuite testOther and so on)
How can I implement this in jUnit?
This is an example of one of the test suites:
#RunWith(Categories.class)
#Suite.SuiteClasses({UserLogin.class,
ExampleTests.class
}
)
public class FirstTest {
I believe you can do something like that using junit test categories. For example, for running integration tests, you can configure a separate annotation for the tests.
Maven supports test categories.
Does it solve your problem or is the jenkins input parameter critical? If it is a jenkins parameter, I believe it is some environment/build configuration and you can customize your build (maven tests to be run) as per the the environment or build job.
I have a simple Groovy test class using JUnit
class GroovyJunitTest {
#Test
void test() {
println this.class.getClassLoader().toString()
}
}
This prints out
sun.misc.Launcher$AppClassLoader#4e25154f
which means that Java classloader is used.
I run the test with both Intellij IDE and using gradle test. The same result is in both cases.
Is there a way to configure JUnit to use Groovy classloader?
Once I had the same problem and I used https://github.com/bitstrings/junit-clptr
to load my custom classloader.
Note: this is no longer supported by the crator however for me it did work out. Anyway if it's to important to trust an outside source you can take it as an inspiration and define your own annotation that will let you choose your custom classloader
I have a bunch of JUnit tests that extend my base test class called BaseTest which in turn extends Assert. Some of my tests have a #Category(SlowTests.class) annotation.
My BaseTest class is annotated with the following annotation #RunWith(MyJUnitRunner.class).
I've set up a Gradle task that is expected to run only SlowTests. Here's my Gradle task:
task integrationTests(type: Test) {
minHeapSize = "768m"
maxHeapSize = "1024m"
testLogging {
events "passed", "skipped", "failed"
outputs.upToDateWhen {false}
}
reports.junitXml.destination = "$buildDir/test-result"
useJUnit {
includeCategories 'testutils.SlowTests'
}
}
When I run the task, my tests aren't run. I've pinpointed this issue to be related to the custom runner MyJUnitRunner on the BaseTest. How can I set up my Gradle or test structure so that I can use a custom runner while using the Suite.
The solution to this turned out to smaller and trickier than I thought. Gradle was using my custom test runner and correctly invoking the filter method. However, my runner reloads all test classes through its own classloader for Javaassist enhancements.
This lead to the issue that SlowTest annotation was loaded through the Gradle classloader but when passed to my custom runner, the runner checked if the class was annotated with that annotation. This check never resolved correctly as the equality of the SlowTest annotation loaded through two different classloaders was different.
--
Since I've already done the research, I'll just leave this here. After days of digging through the Gradle and the (cryptic) JUnit sources, here's what I got.
Gradle simply doesn't handle any advanced JUnit functionality except the test categorization. When you create a Gradle task with the include-categories or the exclude-categories conditions, it builds a CategoryFilter. If you don't know, a Filter is what JUnit gives to the test-runner to decide whether a test or a test method should be filtered out. The test runner must implement the Filterable interface.
JUnit comes with multiple runners, the Categories is just another one of them. It extends a family of test runners called Suite. These suite based runners are designed to run a "suite" of tests. A suite of tests could be built by annotation introspection, by explicitly defining tests in a suite or any other method that builds a suite of tests.
In the case of the Categories runner, JUnit has it's own CategoryFilter but Gradle doesn't use that, it uses it's own CategoryFilter. Both provide more or less the same functionality and are JUnit filters so that can be used by any suite that implements Filterable.
The actual class in the Gradle responsible for running the JUnit tests is called JUnitTestClassExecuter. Once it has parsed the command line options it requests JUnit to check the runner should be used for a test. This method is invoked for every test as seen here.
The rest is simply up to JUnit. Gradle just created a custom RunNotifier to generate the standard XML files representing test results.
I hope someone finds this useful and saved themselves countless hours of debugging.
TLDR: You can use any runner in Gradle. Gradle has no specifics pertaining to runners. It is JUnit that decided the runners. If you'd like to know what runner will be used for your test, you can debug this by calling
Request.aClass(testClass).getRunner(). Hack this somewhere into your codebase and print it to the console. (I wasn't very successful in attaching a debugger to Gradle.)
Is there any alternate way to run the cucumber without Junit.
Is that any possible way to run cucumber as a Java application.. like if I create a main() method and control all step definitions over there?
Any help will be awesome
The answer is out of date. The cucumber docs have this to say, "Running Cucumber
There are several ways to run scenarios with Cucumber-JVM:
JUnit Runner
CLI Runner
Android Runner
Third party runners
"
Cucumber JVM can be invoked from command line. So the answer below applies to any Java codes that can be invoked from command line, not just for Cucumber JVM (which is just another Java component/library).
You can invoke any Java main method from your own main method (or any other methods) through static method invocation. We just need to simulate how the command line arguments being passed.
So if you are able invoke the Cucumber JVM from command line:
java -jar cucumber-jvm.jar cucumber.api.cli.Main --strict --glue com.mycompany.glue --plugin pretty
This is an example how you can do that from your own Java code:
public class MyMainClass {
public void main(String[] args) {
String[] args = new String[] {
"--strict",
"--glue",
"com.mycompany.glue",
"--plugin",
"pretty"
};
cucumber.api.cli.Main.main(args);
}
}
Cucumber is just another custom Junit runner.
so can not have cucumber without Junit.
I converted a dynamically generated JUnit test suite to TestNG using a #Factory annotation. The tests are generated by scanning a directory that contains several test specification files (written in a DSL) and by loading them in an test class that knows how to execute them. The test class has a single #Test method named test, implements org.testng.ITest and overrides getTestName() as recommended.
However, in the TestNG Eclipse UI, only the factory and a single execution of test is shown (although it is executed several times, as expected). With JUnit, I had the name of each spec listed as a separate test. This is very important because several test specs could fail and I would need to see all failures (which does not work in the TestNG Eclipse UI for me).
How can I achieve something similar with TestNG? I use the Eclipse TestNG plugin 6.7.0 and testng 6.7.
Try extending XmlTest in your test class and call setName(). I extended XmlSuite and used setName to name my "test suite" which is a class with multiple tests defined in it and that worked for me. In fact I just tried what I suggested on the same class and now it's called a test with the correct name. I'm not sure why the ITest interface is being ignored as I also tried that approach without success.
As carlin.scott suggested, extending XmlTest works for this problem. However, I overrode toString() to return the test name (instead of calling setName). This has the advantage that the test name in the TestNG view is easier to read. By default, it contains additional information such as parameters and metagroups.