NoSuchMethodError after run JUnit test with Cucumber - java

I'm using Intellij IDEA IDE.
I wrote 2 java classes and 1 feature cucumber file in project. feature structure is:
Feature: First test
with Cucumber
Scenario: Testing
Given file.xml from ext
When take project path
Then run test
Also I wrote 1 jUnit java class for RunTest with Cucumber.class:
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
import org.hamcrest.SelfDescribing;
import gherkin.util.FixJava;
import cucumber.deps.com.thoughtworks.xstream.converters.ConverterRegistry;
#RunWith(Cucumber.class)
public class RunTest {
}
And this is signature of my Test class with cucumber's given, when and then:
public class CallSoapSteps {
//variables for file and path to project
String fileXML = "";
String pathToProj = "";
//take any xml file for insert it into Insert() SoapUI step
#Given("^file.xml from ext$")
public String file_xml_from_ext()
{
//take file
return fileXML = "path_to_xml_file";
}
//any statement about our xml file
#When("^take project path$")
public String take_project_path()
{
//take path to project
return pathToProj = "path_to_soap_project";
}
//any properties for our steps and running SoapTest
#Then("^run test$")
public void run_test() throws Exception {
//add test project
WsdlProject project = new WsdlProject(take_project_path());
//add xml file for test into property
project.setPropertyValue("File", file_xml_from_ext());
//get TestSuite and TestCase by name
TestSuite testSuite = project.getTestSuiteByName("Test");
TestCase testCase = testSuite.getTestCaseByName("Test");
//run test
testCase.run(new PropertiesMap(), false);
}
}
But if I try run jUnit Test, I catched this exception:
java.lang.NoSuchMethodError: gherkin.formatter.model.Scenario.getId()Ljava/lang/String;
And I don't know in which reasons I see this exception.
Also I see this before exception:
0 Scenarios
0 Steps
0m0.000s
As I know, Ljava/lang/String cheked if I string arrays as strings. But in this code I haven't arrays.
UPDATE.
So, I find reason for this exception.
Need to use gherkin 2.12.2.

In the Exception you provided above java.lang.NoSuchMethodError: gherkin.formatter.model.Scenario.getId()Ljava/lang/String;
i think you are using gherkin 2.12.0.jar which does not have getId function in the specified class
Please use gherkin 2.12.2.jar and place this jar in your project build path and try executing

Related

JUnit Test not finding parent class in same package

Im in IntellijIdea, trying to extract some logic from my tests to be reused in others. The problem is everytime I create another class (in the same test package); the test runs fine, but then stops finding the other file, throwing a 'java: cannot find symbol' error. It seems to happen whenever I make changes to the orginal file. It's the same for any new class I try to create, not just the abstract parent class in this example.
I've searched similar questions here, and because the test works at first this seemed promising IntelliJ can't find classes in same package when compiling. But, there were no scripts excepted when I checked.
Currently I'm running my unit tests by just right clicking my tests folder and selecting 'Run all tests', or just running the individual test the same way.
I would be very grateful for any insights.
EDIT: Thanks for fixing the image formatting issue for me.
I also added the source code for the two classes as requested. I still feel like leaving the images is a good idea though, as I mainly meant to communicate the project structure and errors. Also, I want to stress that the problem is code independend I would say, since it persists with any two files.
Note that nonsensical line 51 of the InfoTest ("line = line;") was added to replicate the error. Any change to the original class causes any other class in the package to not be found. You can even see it's not present in the image showing the test running fine.
Extracted class:
package CommandProcessing;
import GameLogic.Game;
import org.junit.jupiter.api.BeforeEach;
import java.lang.reflect.Field;
import static org.junit.jupiter.api.Assertions.fail;
public abstract class InputSimulator {
protected Game game;
protected CommandParser commandParser;
#BeforeEach
void setUp() {
game = new Game();
try {
Class<?> gameClass = game.getClass();
Field cmdField = gameClass.getDeclaredField("commandParser");
cmdField.setAccessible(true);
commandParser = (CommandParser)cmdField.get(game);
} catch (Exception e){
fail(e);
}
}
protected void simulateInput(String input){
commandParser.handleInput(input);
}
class InputTestCase {
private String input;
private String expected;
public InputTestCase(String input, String expected){
this.input = input;
this.expected = expected;
}
public String getInput() { return input; }
public String getExpected() { return expected; }
}
}
Original class:
package CommandProcessing;
import Database.*;
import GameLogic.Game;
import Ship.*;
import IOHandler.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.util.ArrayList;
import static org.junit.jupiter.api.Assertions.*;
class InfoTest extends InputSimulator {
private final InputTestCase[] testCases =
{
new InputTestCase("info cpit", "Cockpit - health: 100.0, shields: 100.0"),
new InputTestCase("info engi", "Engine - health: 100.0, shields: 100.0"),
new InputTestCase("info shld", "Shields - health: 100.0, shields: 100.0"),
new InputTestCase("info weap", "Weapons - health: 100.0, shields: 100.0"),
new InputTestCase("info tank", "FuelTank - health: 100.0, shields: 100.0"),
new InputTestCase("info carg", "CargoBay - health: 100.0, shields: 100.0")
};
#Test
void printPartsOnInfo() {
simulateInput("info");
ArrayList<String> expected = new ArrayList<String>();
expected.add(game.dbAccess().getMessage(Message.Info));
for(PartType part : PartType.values()){
String partString = part.toString();
expected.add(partString);
}
ArchiveAccess archiveAccess = game.getArchiveAccess();
ArrayList<String> lines = archiveAccess.getOutput();
assertEquals(expected, lines);
}
#Test
void printPartDetails() {
for (InputTestCase testCase : testCases) {
simulateInput(testCase.getInput());
ArchiveAccess archiveAccess = game.getArchiveAccess();
String line = archiveAccess.lastOutput();
line = line;
assertEquals(testCase.getExpected(), line);
}
}
}
All errors:
Test running fine the first time:
No Excludes:
So, the problem was that the test root folder was in my source folder!
I actually had the right answer at one time, but read it badly:
How to create a test directory in Intellij 13?.
The test root folder should be next to a main folder which should be the one marked as the source root, not their parent 'src' folder. I had marked this parent directory as the source root - that is to say, the default source root was already called 'src' and I managed to put my test root folder in it, a project structure suspiciously hard to replicate as it would turn out. I got confused because of the naming.
It's a mystery to me how I got it to work in the first place, because when I tried to reproduce the problem it required some detours to get my test root inside my source root. And even then the tests couldn't even find the JUnit package at runtime (they did compile fine though).

Tagged Cucumber Scenarios Functioning

I have been experiencing something really weird. Maybe someone can explain me where I am making mistake.
I have a following scenario in a feature file
#DeleteUserAfterTest
Scenario: Testing a functionality
Given admin exists
When a user is created
Then the user is verified
My #After method in Hooks class looks like following
#After
public void tearDown(Scenario scenario) {
if (scenario.isFailed()) {
final byte[] screenshot = ((TakesScreenshot) driver)
.getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png"); //stick it in the report
}
driver.quit();
}
I am using the following method in my step definition to delete the created user based on tag passed in the Test Scenario as follows:
#After("#DeleteUserAfterTest")
public void deleteUser(){
//Do fucntionalities to delete user
}
My test runner looks something like this:
import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
#CucumberOptions(
plugin = {"pretty","com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:", "json:target/cucumber-report/TestResult.json"},
monochrome = false,
features = "src/test/resources/features/IntegrationScenarios.feature",
tags="#DeleteUserAfterTest",
glue="Steps")
public class IntegrationTest extends AbstractTestNGCucumberTests {
}
However, when I launch the test case, sometimes my user is deleted in the After("#DeleteUserAfterTest") but sometimes my test does not recognises the tagged After at all. It directly goes to After method in my Hooks class and quits the driver. Maybe someone has encountered this problem or knows a workaround!
Method order is not defined in Java. So you have to tell Cucumber in which order you hooks should be executed. Higher numbers are run first (before hooks are the other way around).
#After(order = 500)
public void tearDown(Scenario scenario) {
}
#After(value = "#DeleteUserAfterTest", order = 1000)
public void deleteUser(){
}

picocli: why does this JUnit test fail?

Test won't run correctly trying to run a JUnit test errors
package picocli;
import picocli.CommandLine.Option;
public class ComparatorRunnerConfig {
#Option(names = {"-rc", "--report-class"}, required = false,
description = "define report")
private String report;
public String getReport() {
return report;
}
}
My JUnit test:
package picocli;
import static org.junit.Assert.*;
import org.junit.Test;
public class ConfigurationTest {
#Test
public void testBasicConfigOptions() {
String args = "-rc BlahBlah";
ComparatorRunnerConfig mfc = new ComparatorRunnerConfig();
new CommandLine(mfc).parse(args);
String myTestValue = mfc.getReport();
assertEquals(myTestValue, "BlahBlah");
}
}
Test fails.
The problem is that the test has a subtle bug: the intention is to pass two arguments: the option "-rc" and its option parameter "BlahBlah", but what the test actually does is pass a single argument "-rc BlahBlah" with an embedded space.
Picocli will not be able to match this input and will throw an exception (probably the error message says something like “unknown option -rc BlahBlah”, but I’m away from my pc now, so cannot verify).
The solution is to change the test to either this:
String[] args = "-rc BlahBlah".split(" ");
or this:
String[] args = new String[] {"-rc", "BlahBlah"};
This bug in the test is actually a fairly common mistake and I’ve made this mistake myself a few times. :-)
As a side-note: you can use picocli’s tracing feature to help with troubleshooting issues like this, by setting system property -Dpicocli.trace=DEBUG.

Intellij IDEA - How to run specific testng groups in a class?

I have a maven java project in the latest Intellij IDEA with Testng plugin. I want to run specific groups in a test class without manually creating an xml config file for this.
Can I do that through the run configuration menu instead ? Unfortunately, the menu only lets me select groups, classes, methods etc. but not the groups inside a particular class.
Let's assume you have the following code sample:
import org.testng.annotations.*;
public class Test1 {
#Test(groups = { "functest", "checkintest" })
public void testMethod1() {
}
#Test(groups = {"functest", "checkintest"} )
public void testMethod2() {
}
#Test(groups = { "functest" })
public void testMethod3() {
}
}
To run only checkintest group go to Run Configuration, create new TestNG config -> select Test kind "Group" -> select checkintest group.
Only testMethod1, testMethod2 will be run.

Running Cucumber project using Main.run from another main method

I am new to Cucumber and trying to solve simple issue:
I have created a Java Project and referred all the cucumber related jars to the build-path of this project (called it "CukeTest4") and below is the structure showing the java file and feature file. When I run this feature file as Cucumber feature in Eclipse, it runs fine.
Now, I would like to run this from another main method. I created another Java Project, Added a Class with main method with code below which is in default package.
import cucumber.api.cli.Main;
public class UseCukeFromMain {
public static void main(String[] args) throws Throwable
{
Main.main(new String[]{"-g", "C:/work/workspaces/neon2_wks_new1/Cuketest4/src/com/cuke", "C:/work/workspaces/neon2_wks_new1/Cuketest4/src/com/cuke/cukefeature.feature"});
}
}
I have provided implementation for the method in the java file as it works fine from Eclipse but shows the message below to implement the method
[33mU[0m
1 Scenarios ([33m1 undefined[0m)
1 Steps ([33m1 undefined[0m)
0m0.000s
You can implement missing steps with the snippets below:
#Given("^I want to write a step with precondition$")
public void i_want_to_write_a_step_with_precondition() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I have tried a lot of combination for -g option, but the message is same.
EDIT2
From the comments below, adding the package to glue when the other project is in classpath, works fine.
Main.main(new String[]{"-g", "com.cuke", "C:/work/workspaces/neon2_wks_new1/Cuketest4/src/com/cuke/cukefeature.feature"};
But, Another issue:
I have some old projects that I need to integrate with cucumber. All the .class and .java are present in the folder(NO src or bin directory):
C:\work\RFT_WS2\Cuketest3
, I have this directory in the Classpath. I have tried following option but unable to understand the issue:
-g "" path/to/feature //(NOT WORKING)
-g "classpath:" path/to/feature //(NOT WORKING)
-g "Cuketest3" // Added "C:\work\RFT_WS2" in classpath (NOT WORKING)
Now if I add the .java file to a package say "steps" and have "C:\work\RFT_WS2\Cuketest3" in classpath, option looks like
-g "steps" path/to/feature //(WORKING)
My question is that how to get it to find the methods implementation for a default package.
Also how do add multiple glue option, for example
Not Working cases I tried
Main.main(new String[]{"-g", "com.cuke,com.cuke1", "C:/work/workspaces/neon2_wks_new1/Cuketest4/src/com/cuke/cukefeature.feature"};
Main.main(new String[]{"-g", "com.cuke", "com.cuke1", "C:/work/workspaces/neon2_wks_new1/Cuketest4/src/com/cuke/cukefeature.feature"};
Thanks.
The glue option takes a path value which reflects the package(s) of the glue classes to be included in the classpath.
Find a simplified working example below
Assume following structure
/tmp/cuke-test/features/cukefeature.feature
/tmp/cuke-test/lib
/tmp/cuke-test/project1/src/com/cuke/CukeSteps.java
/tmp/cuke-test/project2/src/UseCukeFromMain.java
cukefeature.feature
Feature: simple test
Scenario: test programatic call of Cucumber
Given we have feature file
When some glue code exists
Then those steps should not fail
lib
cucumber-core-2.1.0.jar
cucumber-html-0.2.6.jar
cucumber-java-2.1.0.jar
cucumber-jvm-deps-1.0.6.jar
cucumber-testng-2.1.0.jar
gherkin-5.0.0.jar
jcommander-1.64.jar
snakeyaml-1.17.jar
tag-expressions-1.0.1.jar
testng-6.11.jar
CukeSteps.java
package com.cuke;
import cucumber.api.PendingException;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.*;
public class CukeSteps {
#Given("^we have feature file$")
public void we_have_feature_file() throws Throwable {
System.out.println("execute Given step");
}
#When("^some glue code exists$")
public void some_glue_code_exists() throws Throwable {
System.out.println("execute Then step");
}
#Then("^those steps should not fail$")
public void those_steps_should_not_fail() throws Throwable {
throw new PendingException();
}
}
UseCukeFromMain.java
import cucumber.api.cli.Main;
public class UseCukeFromMain {
public static void main(String[] args) throws Throwable {
Main.main(new String[]{
"--glue",
"com/cuke", // the package which contains the glue classes
"/tmp/cuke-test/features/cukefeature.feature"}
);
}
}
compile the classes
javac -cp "lib/*" -d project1/bin/ project1/src/com/cuke/*.java
javac -cp "lib/*" -d project2/bin/ project2/src/*.java
run the UseCukeFromMain
The root direcotry which contains the glue classes (project1/bin) must be in the classpath.
java -cp "project2/bin:project1/bin:lib/*" UseCukeFromMain
output
execute Given step
execute Then step
1 Scenarios (1 pending)
3 Steps (1 pending, 2 passed)
0m0.104s
cucumber.api.PendingException: TODO: implement me
at com.cuke.CukeSteps.those_steps_should_not_fail(CukeSteps.java:21)
at ✽.those steps should not fail(/tmp/cuke-test/features/cukefeature.feature:6)
edit Using Step definitions in default package
Assume following structure
features/cukefeature.feature
lib/
project1/src/CukeSteps.java
project2/src/UseCukeFromMain.java
cukefeature.feature
lib/
the same as in the first example
CukeSteps.java
// note: there is no package statement
import cucumber.api.PendingException;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.*;
public class CukeSteps {
#Given("^we have feature file$")
public void we_have_feature_file() throws Throwable {
System.out.println("execute Given step");
}
#When("^some glue code exists$")
public void some_glue_code_exists() throws Throwable {
System.out.println("execute Then step");
}
#Then("^those steps should not fail$")
public void those_steps_should_not_fail() throws Throwable {
throw new PendingException();
}
}
UseCukeFromMain.java
import cucumber.api.cli.Main;
public class UseCukeFromMain {
public static void main(String[] args) throws Throwable {
Main.main(new String[]{
"--glue",
"", // to used Step definitions in default package
"features/cukefeature.feature"}
);
}
}
compile classes
The option -d . creates the class files in the current directory.
javac -cp "lib/*" -d . project1/src/*.java
javac -cp "lib/*" -d project2/bin/ project2/src/*.java
created class files
CukeSteps.class
project2/bin/UseCukeFromMain.class
run the UseCukeFromMain
The current directory is added to the classpath using the ..
java -cp "project2/bin:.:lib/*" UseCukeFromMain
output
execute Given step - default package
execute Then step - default package
1 Scenarios (1 pending)
3 Steps (1 pending, 2 passed)
0m0.096s
cucumber.api.PendingException: TODO: implement me
at CukeSteps.those_steps_should_not_fail(CukeSteps.java:19)
at ✽.those steps should not fail(features/cukefeature.feature:5)
edit Using Step definitions from different packages.
Assume following structure
features/cukefeature.feature
lib
project1/src/com/cuke1/CukeStepsB.java
project1/src/com/cuke/CukeStepsA.java
project2/src/UseCukeFromMain.java
cukefeature.feature
lib/
the same as in the first example
The Step definitions are split in two classes, in different packages
CukeStepsA.java
package com.cuke;
import cucumber.api.PendingException;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.*;
public class CukeStepsA {
#Given("^we have feature file$")
public void we_have_feature_file() throws Throwable {
System.out.println("execute Given step - package com.cuke");
}
}
CukeStepsB.java
package com.cuke1;
import cucumber.api.PendingException;
import cucumber.api.Scenario;
import cucumber.api.java.Before;
import cucumber.api.java.en.*;
public class CukeStepsB {
#When("^some glue code exists$")
public void some_glue_code_exists() throws Throwable {
System.out.println("execute Then step - package com.cuke1");
}
#Then("^those steps should not fail$")
public void those_steps_should_not_fail() throws Throwable {
throw new PendingException();
}
}
UseCukeFromMain.java
import cucumber.api.cli.Main;
public class UseCukeFromMain {
public static void main(String[] args) throws Throwable {
Main.main(new String[]{
"--glue",
"com/cuke",
"--glue",
"com/cuke1",
"features/cukefeature.feature"}
);
}
}
compile classes
javac -cp "lib/*" -d project1/bin/ project1/src/com/cuke/*.java project1/src/com/cuke1/*.java
javac -cp "lib/*" -d project2/bin/ project2/src/*.java
created class files
project1/bin/com/cuke1/CukeStepsB.class
project1/bin/com/cuke/CukeStepsA.class
project2/bin/UseCukeFromMain.class
run the UseCukeFromMain
java -cp "project2/bin:project1/bin:lib/*" UseCukeFromMain
output
execute Given step - package com.cuke
execute Then step - package com.cuke1
1 Scenarios (1 pending)
3 Steps (1 pending, 2 passed)
0m0.114s
cucumber.api.PendingException: TODO: implement me
at com.cuke1.CukeStepsB.those_steps_should_not_fail(CukeStepsB.java:16)
at ✽.those steps should not fail(features/cukefeature.feature:5)
The absolute path is required for feature file. The step def directory requires classpath format.
public static void main(String[] args) throws Throwable {
//Your code to get feature file full path
Main.main(new String[]{"-g", "classpath to step definition file", "Full path to feature file"});
}

Categories