Cucumber - How to configure QAF Gherkin Scenario Factory? - cucumber

I have a Cucumber project running thanks to JUnit with the following class:
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/test/resources/features",
glue = "com.steps",
plugin = {"pretty", "json:target/cucumber-report/cucumber.json"})
public class RunCucumber {
}
I want to use QAF Gherkin Scenario Factory in order to put some scenario examples in external files in order to reuse them (ex : Cucumber: Scenario Outline reusing examples table or CustomDataProvider for feature file (QAF)).
I read the last section called "For Existing cucumber implementation" and did what it says, but I currently get an exception when running Cucumber with QAF (see edit section below).
Java: 1.8
Cucumber : 4.8.0
Junit: 4.12
src/test/resources/features/test.feature
Feature: Test for QAF
Scenario: success
Given my scenario works
src/test/java/com/steps/TestSteps.java
#QAFTestStepProvider
public class TestSteps {
#Given("my scenario works")
public void myScenarioWorks() {
assertTrue(true);
}
}
Edit: Base on user861594 help, here is where I am:
I downloaded the library QAF 2.1.15 through maven configuration.
<dependency>
<groupId>com.qmetry</groupId>
<artifactId>qaf</artifactId>
<version>2.1.15</version>
</dependency>
I annotated my step class with #QAFTestStepProvider
I created a xml configuration file for testNG in order to configure cucumber and run it with the QAF class called GherkinScenarioFactory:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestNG - Cucumber" verbose="0">
<test name="Gherkin-QAF-Test">
<parameter name="step.provider.pkg" value="com.steps" />
<parameter name="scenario.file.loc" value="src/test/resources/features/test.feature" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
</suite>
I ran the previous configuration with the testNG plugin for IntelliJ IDEA (test kind = suite. I also can choose Class, Method, Group, Pattern or All in package)
When running, I get the following exception (before the test, so it is ignored):
"C:\Program Files\Java\jdk1.8.0_212\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\lib\idea_rt.jar=51974:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\plugins\testng\lib\testng-plugin.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\rt.jar;C:\Utilisateurs\a754206\IdeaProjects\perso\cucumber\target\test-classes;C:\Utilisateurs\a754206\IdeaProjects\perso\cucumber\target\classes;C:\Utilisateurs\a754206\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Utilisateurs\a754206\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\cucumber-java\4.8.0\cucumber-java-4.8.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\cucumber-core\4.8.0\cucumber-core-4.8.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\gherkin\5.1.0\gherkin-5.1.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\tag-expressions\1.1.1\tag-expressions-1.1.1.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\cucumber-expressions\7.0.2\cucumber-expressions-7.0.2.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\datatable\1.1.14\datatable-1.1.14.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\datatable-dependencies\1.1.14\datatable-dependencies-1.1.14.jar;C:\Utilisateurs\a754206\.m2\repository\org\apiguardian\apiguardian-api\1.1.0\apiguardian-api-1.1.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\cucumber-junit\4.8.0\cucumber-junit-4.8.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\cucumber\cucumber-spring\4.8.0\cucumber-spring-4.8.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-context\5.2.0.RELEASE\spring-context-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-aop\5.2.0.RELEASE\spring-aop-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-beans\5.2.0.RELEASE\spring-beans-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-core\5.2.0.RELEASE\spring-core-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-jcl\5.2.0.RELEASE\spring-jcl-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\org\springframework\spring-expression\5.2.0.RELEASE\spring-expression-5.2.0.RELEASE.jar;C:\Utilisateurs\a754206\.m2\repository\net\masterthought\cucumber-reporting\4.10.0\cucumber-reporting-4.10.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\apache\velocity\velocity\1.7\velocity-1.7.jar;C:\Utilisateurs\a754206\.m2\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;C:\Utilisateurs\a754206\.m2\repository\velocity-tools\velocity-tools\1.4\velocity-tools-1.4.jar;C:\Utilisateurs\a754206\.m2\repository\joda-time\joda-time\2.10.2\joda-time-2.10.2.jar;C:\Utilisateurs\a754206\.m2\repository\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;C:\Utilisateurs\a754206\.m2\repository\commons-io\commons-io\2.6\commons-io-2.6.jar;C:\Utilisateurs\a754206\.m2\repository\org\codehaus\plexus\plexus-utils\3.2.0\plexus-utils-3.2.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\jsoup\jsoup\1.12.1\jsoup-1.12.1.jar;C:\Utilisateurs\a754206\.m2\repository\com\googlecode\owasp-java-html-sanitizer\owasp-java-html-sanitizer\20190610.1\owasp-java-html-sanitizer-20190610.1.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\guava\guava\27.1-jre\guava-27.1-jre.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;C:\Utilisateurs\a754206\.m2\repository\org\checkerframework\checker-qual\2.5.2\checker-qual-2.5.2.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\errorprone\error_prone_annotations\2.2.0\error_prone_annotations-2.2.0.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\j2objc\j2objc-annotations\1.1\j2objc-annotations-1.1.jar;C:\Utilisateurs\a754206\.m2\repository\org\codehaus\mojo\animal-sniffer-annotations\1.17\animal-sniffer-annotations-1.17.jar;C:\Utilisateurs\a754206\.m2\repository\commons-configuration\commons-configuration\1.10\commons-configuration-1.10.jar;C:\Utilisateurs\a754206\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Utilisateurs\a754206\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Utilisateurs\a754206\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Utilisateurs\a754206\.m2\repository\com\jayway\jsonpath\json-path\2.2.0\json-path-2.2.0.jar;C:\Utilisateurs\a754206\.m2\repository\net\minidev\json-smart\2.2.1\json-smart-2.2.1.jar;C:\Utilisateurs\a754206\.m2\repository\net\minidev\accessors-smart\1.1\accessors-smart-1.1.jar;C:\Utilisateurs\a754206\.m2\repository\org\ow2\asm\asm\5.0.3\asm-5.0.3.jar;C:\Utilisateurs\a754206\.m2\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;C:\Utilisateurs\a754206\.m2\repository\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;C:\Utilisateurs\a754206\.m2\repository\commons-logging\commons-logging\1.2\commons-logging-1.2.jar;C:\Utilisateurs\a754206\.m2\repository\commons-codec\commons-codec\1.9\commons-codec-1.9.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.9.8\jackson-databind-2.9.8.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.9.8\jackson-core-2.9.8.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\jackson\dataformat\jackson-dataformat-xml\2.9.8\jackson-dataformat-xml-2.9.8.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\jackson\module\jackson-module-jaxb-annotations\2.9.8\jackson-module-jaxb-annotations-2.9.8.jar;C:\Utilisateurs\a754206\.m2\repository\org\codehaus\woodstox\stax2-api\3.1.4\stax2-api-3.1.4.jar;C:\Utilisateurs\a754206\.m2\repository\com\fasterxml\woodstox\woodstox-core\5.0.3\woodstox-core-5.0.3.jar;C:\Utilisateurs\a754206\.m2\repository\com\qmetry\qaf\2.1.15\qaf-2.1.15.jar;C:\Utilisateurs\a754206\.m2\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\Utilisateurs\a754206\.m2\repository\com\sun\jersey\jersey-client\1.19\jersey-client-1.19.jar;C:\Utilisateurs\a754206\.m2\repository\com\sun\jersey\jersey-core\1.19\jersey-core-1.19.jar;C:\Utilisateurs\a754206\.m2\repository\javax\ws\rs\jsr311-api\1.1.1\jsr311-api-1.1.1.jar;C:\Utilisateurs\a754206\.m2\repository\com\sun\jersey\contribs\jersey-multipart\1.19\jersey-multipart-1.19.jar;C:\Utilisateurs\a754206\.m2\repository\org\jvnet\mimepull\mimepull\1.9.3\mimepull-1.9.3.jar;C:\Utilisateurs\a754206\.m2\repository\com\sun\jersey\contribs\jersey-apache-client\1.17.1\jersey-apache-client-1.17.1.jar;C:\Utilisateurs\a754206\.m2\repository\commons-httpclient\commons-httpclient\3.1\commons-httpclient-3.1.jar;C:\Utilisateurs\a754206\.m2\repository\org\aspectj\aspectjrt\1.8.9\aspectjrt-1.8.9.jar;C:\Utilisateurs\a754206\.m2\repository\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar;C:\Utilisateurs\a754206\.m2\repository\org\aspectj\aspectjtools\1.8.9\aspectjtools-1.8.9.jar;C:\Utilisateurs\a754206\.m2\repository\net\sourceforge\jexcelapi\jxl\2.6.12\jxl-2.6.12.jar;C:\Utilisateurs\a754206\.m2\repository\log4j\log4j\1.2.14\log4j-1.2.14.jar;C:\Utilisateurs\a754206\.m2\repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;C:\Utilisateurs\a754206\.m2\repository\org\testng\testng\6.10\testng-6.10.jar;C:\Utilisateurs\a754206\.m2\repository\com\beust\jcommander\1.48\jcommander-1.48.jar;C:\Utilisateurs\a754206\.m2\repository\com\google\inject\guice\3.0\guice-3.0.jar;C:\Utilisateurs\a754206\.m2\repository\javax\inject\javax.inject\1\javax.inject-1.jar;C:\Utilisateurs\a754206\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Utilisateurs\a754206\.m2\repository\velocity\velocity-dep\1.4\velocity-dep-1.4.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-remote-driver\2.53.0\selenium-remote-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\cglib\cglib-nodep\2.1_3\cglib-nodep-2.1_3.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-api\2.53.0\selenium-api-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\apache\commons\commons-exec\1.3\commons-exec-1.3.jar;C:\Utilisateurs\a754206\.m2\repository\net\java\dev\jna\jna\4.1.0\jna-4.1.0.jar;C:\Utilisateurs\a754206\.m2\repository\net\java\dev\jna\jna-platform\4.1.0\jna-platform-4.1.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-java\2.53.0\selenium-java-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-chrome-driver\2.53.0\selenium-chrome-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-edge-driver\2.53.0\selenium-edge-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-firefox-driver\2.53.0\selenium-firefox-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-ie-driver\2.53.0\selenium-ie-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-safari-driver\2.53.0\selenium-safari-driver-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\io\netty\netty\3.5.7.Final\netty-3.5.7.Final.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-support\2.53.0\selenium-support-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\seleniumhq\selenium\selenium-leg-rc\2.53.0\selenium-leg-rc-2.53.0.jar;C:\Utilisateurs\a754206\.m2\repository\org\json\json\20180813\json-20180813.jar;C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\plugins\testng\lib\jcommander-1.27.jar" org.testng.RemoteTestNGStarter -usedefaultlisteners false -socket51973 #w#C:\Utilisateurs\a754206\AppData\Local\Temp\idea_working_dirs_testng.tmp -temp C:\Utilisateurs\a754206\AppData\Local\Temp\idea_testng.tmp
10:00:20.385 [main] INFO c.q.q.a.core.ConfigurationManager - ISFW build info: {qaf-Type=core, qaf-Revision=15, qaf-Version=2.1, qaf-Build-Time=20-Nov-2019 22:28:06}
10:00:20.409 [main] INFO c.q.q.a.core.ConfigurationManager - Resource dir: C:\Utilisateurs\a754206\IdeaProjects\perso\cucumber\resources. Found property files to load: 0
10:00:20.417 [main] INFO c.q.q.a.core.ConfigurationManager - Resource dir: C:\Utilisateurs\a754206\IdeaProjects\perso\cucumber\resources. Found property files to load: 0
include groups []
exclude groups: [] Scanarios location: src/test/resources/features/test.feature
10:00:20.430 [main] INFO c.q.q.a.s.c.g.GherkinScenarioFactory - scenario.file.loc[Ljava.lang.String;#2a40cd94
10:00:20.511 [main] INFO c.q.q.a.s.c.text.BehaviorScanner - loading feature file: src/test/resources/features/test.feature
10:00:20.542 [main] INFO c.q.q.a.s.c.g.GherkinScenarioFactory - total test found: 1
Test ignored.
Preparing For Shut Down...
java.lang.NullPointerException
at java.util.ArrayList.<init>(ArrayList.java:178)
at com.qmetry.qaf.automation.testng.pro.QAFTestNGListener.report(QAFTestNGListener.java:234)
at com.qmetry.qaf.automation.testng.pro.QAFTestNGListener2.report(QAFTestNGListener2.java:174)
at com.qmetry.qaf.automation.testng.pro.QAFTestNGListener.onConfigurationFailure(QAFTestNGListener.java:126)
at org.testng.internal.Invoker.runConfigurationListeners(Invoker.java:1686)
at org.testng.internal.Invoker.handleConfigurationFailure(Invoker.java:305)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:243)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:144)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:326)
at org.testng.SuiteRunner.run(SuiteRunner.java:289)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
at org.testng.TestNG.runSuites(TestNG.java:1133)
at org.testng.TestNG.run(TestNG.java:1104)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:73)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
I debbuged, and in fact there is a double error: a NullPointerException happens during the run (see below), so then we arrive in onConfigurationFailure, but then again there is a NullPointerException (the one above)
java.lang.NullPointerException
at com.qmetry.qaf.automation.testng.pro.QAFTestNGListener.beforeInvocation(QAFTestNGListener.java:174)
at org.testng.internal.invokers.InvokedMethodListenerInvoker$InvokeBeforeInvocationWithContextStrategy.callMethod(InvokedMethodListenerInvoker.java:92)
at org.testng.internal.invokers.InvokedMethodListenerInvoker$InvokeBeforeInvocationWithContextStrategy.callMethod(InvokedMethodListenerInvoker.java:88)
at org.testng.internal.invokers.InvokedMethodListenerInvoker.invokeListener(InvokedMethodListenerInvoker.java:62)
at org.testng.internal.Invoker.runInvokedMethodListeners(Invoker.java:557)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:494)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:217)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:144)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:326)
at org.testng.SuiteRunner.run(SuiteRunner.java:289)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
at org.testng.TestNG.runSuites(TestNG.java:1133)
at org.testng.TestNG.run(TestNG.java:1104)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:73)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
Recap of when and where the exceptions happen:
// TestNG SuiteRunner#run begins
// Eventually we arrive in QAFTestBase where the first NullPointerException happens
public List<LoggingBean> getLog() {
return (List<LoggingBean>) getContext().getObject(COMMAND_LOG); // NullPointerException. getContext() is OK but getContext().getObject(CHECKPOINTS) returns null
}
// QAFTestNGListener#onConfigurationFailure is called
// Eventually we arrive in QAFTestBase again, where the second NullPointerException happens
public List<CheckpointResultBean> getCheckPointResults() {
return (List<CheckpointResultBean>) getContext().getObject(CHECKPOINTS); // NullPointerException. getContext() is OK but getContext().getObject(CHECKPOINTS) returns null
}

Create XML configuration file to run your features:
<test name="Gherkin-QAF-Test">
<parameter name="step.provider.pkg" value="pkg.to.look.for.steps" />
<parameter name="scenario.file.loc" value="resources/features" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
Refer documentation for BDD configuration. Run it as TestNG test.
Which version of cucumber step implementation you have?
If it is cucumber 5+ add qaf-cucumber dependency. You can find latest dependency in maven central. Also use latest version (as of today QAF 2.1.15)
EDIT:
Cucumber 4:
Cucumber 4 users can use qaf-cucmber4 and keep using cucumber as it is with additional capabilities. It will allow you to use external test data, and parameterize step arguments as well as meta-data rule and meta-data format. Below are steps:
add qaf-cucumber4 dependency. Make suer to put dependency before
other cucumner dependencies.
add QAFCucumberPlugin (see junit example below).
You can then use BDD2 syntax features which is super set of gherkin.
#RunWith(Cucumber.class)
#CucumberOptions(plugin = {"com.qmetry.qaf.automation.cucumber.QAFCucumberPlugin"}, <other options>)//
public class RunCucumberTest {
}
Cucumber 5:
add qaf-cucumber dependency. Make suer to put dependency befor
other cucumner dependencies.
To run using cucumner runner add QAFCucumberPlugin (see junit example above).
To Run using TestNG use QAF BDD2 factory with TestNG
Here is example TestNG configuration file.
<test name="Gherkin-QAF-Test">
<parameter name="step.provider.pkg" value="pkg.to.look.for.steps" />
<parameter name="scenario.file.loc" value="resources/features" />
<classes>
<class name="com.qmetry.qaf.automation.step.client.text.BDDTestFactory2" />
</classes>
</test>
Note: qaf-cucumber4 is not supporting running with testng using bdd factory.

Turns out the exceptions were due to the following dependency, which has nothing to do with QAF as it simply is a plugin to generate cucumber reports in html format:
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>4.10.0</version>
</dependency
Without it, everything is fine. I did not bother to dig why because I don't care and have no time for this.
I am now able to run tests with QAF, but it is important to note that:
#QAFTestStep and #QAFTestStepProvider do not work with cucumber annotations of io.cucumber.java.en.*, but only with their deprecated version of cucumber.api.java.en.*. Otherwise there will be a com.qmetry.qaf.automation.step.StepNotFoundException
Cucumber parameters like {string} must be escaped like \\{string\\} every single time. Otherwise there will be a java.util.regex.PatternSyntaxException: Illegal repetition
Spring dependency injection is more complex with TestNG than it is with Cucumber alone: steps classes must extends AbstractTestNGSpringContextTests (which imply to import the spring-test libray) and be annotated with #ContextConfiguration. Also I could not make this work, so may be it is even more complex when using QAF.
I discovered that while just scraching the surface of TestNG+QAF, so my opinion is that it is not worth the pain if like me you only want to use QAF for its feature of externalizing data.

If you use qaf to run testng with cucumber, in your log there is "include groups []" shows that you didn't include your test case.
So you should add you test case in testng xml like below:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="TestNG - Cucumber" verbose="0">
<test name="Gherkin-QAF-Test">
<parameter name="step.provider.pkg" value="com.steps" />
<parameter name="scenario.file.loc" value="src/test/resources/features/test.feature" />
<groups>
<run>
<include name="#test"/>
</run>
</groups>
<classes>
<class name="com.qmetry.qaf.automation.step.client.gherkin.GherkinScenarioFactory" />
</classes>
</test>
</suite>
And add #test tag in cucumber feature file:
Feature: Test for QAF
#test
Scenario: success
Given my scenario works

This should not be posted in cucumberjs. From what I can see this is Java?

Related

QAF weird behavior for parallel testing

for example:
testing.xml
<suite name="name" parallel="methods" thread-count="5">
<test>
...
</test>
</suite>
case #1: when I run the following feature file with #smoke tag per say, it will execute parallel testing normally:
something1.feature
#smoke
Feature: <feature message>
Scenario: <scenario1 message>
...
Scenario: <scenario2 message>
case#2: when I execute the same scenario using 'Scenario Outlines' is when parallel testing goes concurrently even though the parallel testing configuration is setup in the TestNG xml file.
something2.feature
Feature: <feature message>
Scenario Outline: <scenario outline messsage>
...
Examples:
<data table>
does anybody knows why is this happening with QMETRY framework?
When you are using TestNG, Scenario Outline is converted to TestNG data-driven tests. In TestNG there is separate mechanism for data driven test case parallel execution. QAF provides property global.datadriven.parallel to set parallel behavior for data driven tests. Default value is false. Make sure that you have set it to true in order to run data-driven tests in parallel.
global.datadriven.parallel=true

Invoking groovy method in Mule 4

I have built a complete groovy project with JPA repo for data persistence operations. Now I want to invoke the methods from the script in Mule 4 without changing anything in the groovy project.
eg. CustomerService.groovy (pseudo code)
import com.example.dao.CustomerDao.groovy
... other imports...
#Service
class CustomerService {
#Autowired
CustomerDao cDao
#Transactional
publid Customer createCustomer(Customer customer) {
return cDao.save(customer)
}
... other methods...
}
CustomerDao.groovy
import spring.JPA (the original import path may vary)
#Repository
class CustomerDao implements JPARepository<Customer, Integer> {
}
This project is working in Mule 3. In Mule 3 we have an Invoke component which could be used to invoke the methods from the groovy script. The Mule 4 the Invoke component is compatible only with Java and not groovy.
The Scripting module's 'Execute' component can invoke a groovy script but not sure how to invoke the method. Is the any work around for this in Mule 4?
Problems occured as of now
In 'Execute' component if I import another file I get the error as
Unalbe to resolve class com.example.dao.CustomerDao
# line 3 column 1,
import com.example.dao.CustomerDao.groovy
^
Found a solution for similar problem https://help.mulesoft.com/s/article/Compilation-exception-in-Mule4-x-when-using-Groovy-script-with-Import-statement but unable to implement it.
In the article, he developer had an issue with an apache dependency, which he/she could get from mvn repo. I am trying to import a groovy file which I have developed. So unable to add it in the dependency. I tried adding the groovy project in my local repo and fetch it but it didn't work. Moreover, when this Mule 4 application will be deployed on CloudHub it will have an issue as it won't be able to access my local repo.
Need a solution to add a spring-groovy project to Mule 4
Thanks :)
The problem is that the Groovy script executed by the Scripting Module is trying to import a class, which is not in Java's classpath. So it throws the error. The class is in another Groovy source file. What you can do is to compile the Groovy code into an actual Java class. You can try one the methods described in the Groovy documentation to integrate a Maven plugin with your Mule application pom.xml file.
Another alternative if you have a large number of Groovy classes is to create a separate project to build a Jar library, then use the solution from the KB article you mentioned.

Is additional context configuration required when upgrading cucumber-jvm from version 4 to version 6?

I am using cucumber-jvm to perform some functional tests in Kotlin.
I have the standard empty runner class:
#RunWith(Cucumber::class)
#CucumberOptions(features=[foo],
glue=[bar],
plugin=[baz],
strict=true,
monochrome=true)
class Whatever
The actual steps are defined in another class with the #ContextConfiguration springframework annotation.
This class also uses other spring features like #Autowire or #Qualifier
#ContextConfiguration(locations=["x/y/z/config.xml"])
class MyClass {
...
#Before
...
#Given("some feature file stuff")
...
// etc
}
This all work fine in cucumber version 4.2.0, however upgrading to version 6.3.0 breaks things. After updating the imports to match the new cucumber project layout the tests now fail with this error:
io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.
It provides examples of what it means...
For example:
#CucumberContextConfiguration
#SpringBootTest(classes = TestConfig.class)
public class CucumberSpringConfiguration {}
Or:
#CucumberContextConfiguration
#ContextConfiguration( ... )
public class CucumberSpringConfiguration {}
It looks like it's telling me I can just add #CucumberContextConfiguration to MyClass.
But why?
I get the point of #CucumberContextConfiguration, it's explained well here but why do I need it now with version 6 when version 4 got on fine without it? I can't see any feature that was deprecated and replaced by this.
Any help would be appreciated :)
Since the error matches exactly with the error I was getting in running Cucumber tests with Spring Boot, so I am sharing my fix.
One of the probable reason is: Cucumber can't find the CucumberSpringConfiguration
class in the glue path.
Solution 1:
Move the CucumberSpringConfiguration class inside the glue path (which in my case was inside the steps package).
Solution 2:
Add the CucumberSpringConfiguration package path in the glue path.
The below screenshot depicts my project structure.
As you can see that my CucumberSpringConfig class was under configurations package so it was throwing me the error when I tried to run feature file from command prompt (mvn clean test):
"Please annotate a glue class with some context configuration."
So I applied solution 2, i.e added the configurations package in the glue path in my runner class annotation.
And this is the screenshot of the contents of CucumberSpringConfiguration class:
Just an extra info:
To run tests from command prompt we need to include the below plugin in pom.xml
https://github.com/cucumber/cucumber-jvm/pull/1959 removed the context configuration auto-discovery. The author concluded that it hid user errors and removing it would provide more clarity and reduce complexity. It also listed the scenarios where the context configuration auto-discovery used to apply.
Note that it was introduced after https://github.com/cucumber/cucumber-jvm/pull/1911, which you had mentioned.
Had the same error but while running Cucumber tests from Jar with Gradle.
The solution was to add a rule to the jar task to merge all the files with the name "META-INF/services/io.cucumber.core.backend.BackendProviderService" (there could be multiple of them in different Cucumber libs - cucumber-java, cucumber-spring).
For Gradle it is:
shadowJar {
....
transform(AppendingTransformer) {
resource = 'META-INF/services/io.cucumber.core.backend.BackendProviderService'
}
}
For Maven something like this:
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/io.cucumber.core.backend.BackendProviderService</resource>
</transformer>
</transformers>
A bit more explanation could be found in this answer

How does thread parallelism work for DataProvider in TestNg and how can I specify the threadcount for DataProvider?

We use threadcount attribute in #Test annotation of TestNg but there is no such attribute for #DataProvider annotation so is it possible to specify the thread count for Dataprovider, if yes then how? I specified Parallel=true in #DataProvider annotation and tried to read the data from Excel, there were 19 sets of test data and when executed then by default I found that 10 threads got created. I used Thread.currentThread() along with each set of Test Data to display the thread being used but I failed to understand the process and reason for 10 threads getting created.
That is because 10 is used as the default value by testng when parallel is set to true on a DataProvider. This can be overridden by data-provider-thread-count attribute on the suite tag. Example:
<suite name="Sample Suite" data-provider-thread-count="20">
<test name="Component Tests">
<packages>
<package name="com.something.tests" />
</packages>
</test>
</suite>
The testng documentation on DataProvider has this and much more: http://testng.org/doc/documentation-main.html#parameters-dataproviders

Groovy Griffon with Hibernate4 plugin class not found exception

I was looking for a fast and easy way to write a very cross platform desktop application. This leads me to thinking that the JVM is the place to be. Since Groovy (Grails) is used in my workplace I thought I would try Griffon since they claim it is essentially Grails for the desktop.
I wanted a persistence management layer and it doesn't not appear that GORM is showtime ready in this environment so I moved towards hibernate using the Hibernate4 plugin for Griffon.
Not that I've really used Hibernate in general however I believe, based on the guides, that I am doing things correctly. My gatherings indicate that this doesn't support annotations to wire up classes so I am using hbm.xml files.
The provided sample for the plugin isn't complex but I don't understand where I am deviating.
Here is a sample class file as it stands:
package gwash
import groovy.beans.Bindable
class DeliveryMethodModel {
// #Bindable String propName
}
Here is some of the stack trace:
org.hibernate.InvalidMappingException: Could not parse mapping document from res
ource gwash\DeliveryMethod.hbm.xml
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXml(Con
figuration.java:3415)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXmlQueu
e(Configuration.java:3404)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(C
onfiguration.java:3392)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:
1341)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.jav
a:1737)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.jav
a:1788)
at org.hibernate.cfg.Configuration$buildSessionFactory.call(Unknown Sour
ce)
at griffon.plugins.hibernate4.Hibernate4Connector.connect(Hibernate4Conn
ector.groovy:72)
at griffon.plugins.hibernate4.Hibernate4Connector.connect(Hibernate4Conn
ector.groovy)
at griffon.plugins.hibernate4.Hibernate4Connector$connect.call(Unknown S
ource)
at Hibernate4GriffonAddon.addonInit(Hibernate4GriffonAddon.groovy:27)
at griffon.core.GriffonAddon$addonInit.call(Unknown Source)
at griffon.core.GriffonAddon$addonInit.call(Unknown Source)
at org.codehaus.griffon.runtime.util.AddonHelper.handleAddon(AddonHelper
.groovy:155)
at org.codehaus.griffon.runtime.util.AddonHelper.handleAddonsAtStartup(A
ddonHelper.groovy:105)
at org.codehaus.griffon.runtime.core.DefaultAddonManager.doInitialize(De
faultAddonManager.java:33)
at org.codehaus.griffon.runtime.core.AbstractAddonManager.initialize(Abs
tractAddonManager.java:101)
at org.codehaus.griffon.runtime.util.GriffonApplicationHelper.initialize
AddonManager(GriffonApplicationHelper.java:320)
at org.codehaus.griffon.runtime.util.GriffonApplicationHelper.prepare(Gr
iffonApplicationHelper.java:123)
at org.codehaus.griffon.runtime.core.AbstractGriffonApplication.initiali
ze(AbstractGriffonApplication.java:221)
at griffon.swing.AbstractSwingGriffonApplication.bootstrap(AbstractSwing
GriffonApplication.java:74)
at griffon.swing.AbstractSwingGriffonApplication.run(AbstractSwingGriffo
nApplication.java:131)
at griffon.swing.SwingApplication.main(SwingApplication.java:36)
Caused by: org.hibernate.PropertyNotFoundException: field [id] not found on gwas
h.DeliveryMethodModel
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:182)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:189)
at org.hibernate.property.DirectPropertyAccessor.getField(DirectProperty
Accessor.java:174)
at org.hibernate.property.DirectPropertyAccessor.getGetter(DirectPropert
yAccessor.java:197)
at org.hibernate.internal.util.ReflectHelper.getter(ReflectHelper.java:2
53)
at org.hibernate.internal.util.ReflectHelper.reflectedPropertyClass(Refl
ectHelper.java:229)
at org.hibernate.mapping.SimpleValue.setTypeUsingReflection(SimpleValue.
java:326)
at org.hibernate.cfg.HbmBinder.bindSimpleId(HbmBinder.java:449)
at org.hibernate.cfg.HbmBinder.bindRootPersistentClassCommonValues(HbmBi
nder.java:382)
at org.hibernate.cfg.HbmBinder.bindRootClass(HbmBinder.java:322)
at org.hibernate.cfg.HbmBinder.bindRoot(HbmBinder.java:173)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processHbmXml(Con
My xml mapping file:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="gwash">
<class name="DeliveryMethodModel" table="[DELIVERY METHODS]">
<id name="id" column="[DELIVERY METHOD ID]">
<generator class="increment"/>
</id>
<property name="method" column="[DELIVERY METHOD]"/>
</class>
</hibernate-mapping>
EDIT: I've removed the brackets and spaces as indicated. Changed the DataSource.groovy to 'create' on the DB side. Still experiencing the same issues. The examples for hibernate integration with griffon/hsqldb/groovy are scant on details. Do I need to create all given properties for the model files for this to parse correctly? I've never used hibernate. Nor groovy. Nor griffon. I would definitely provide feedback for the community if I can get this resolved, if not I'll be rolling me own ORM since this is a rather small project. Rather not roll me own.
do you actually have the strings wrapped with [and ]?
I would suspect that for a class defined as
package gwash
import groovy.beans.Bindable
class DeliveryMethodModel {
Long id
#Bindable String method
}
the mapping file would be
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="gwash">
<class name="DeliveryMethodModel" table="DELIVERY_METHODS">
<id name="id" column="DELIVERY_METHOD_ID">
<generator class="increment"/>
</id>
<property name="method" column="DELIVERY_METHOD"/>
</class>
</hibernate-mapping>

Resources