Cucumber JVM using JUnit can't find stepDefinitions - java

I'm having difficult pointing to my stepDefinitions. It exists, it has stuff in it like:
#Given("^Mark \"(.*)\" flew a kite$")
public void mark_flew_a_kite(String kiteName) throws Throwable {
kiteName = kiteName;
}
#When("^The wind blows (\\d+)st (\\d+)$")
public void the_wind_blows() throws Throwable {
json = callKiteService(200);
}
Please note I've changed all the actual method names for stackoverflow and inadvertantly made some of the regex not match. But it matches in the actual code!
But the test output says that none of the test steps were found and that I need to write them all.
Feature: Mark flies kite
Scenario: Mark flew a kite on a windy day [90m# WebServiceTest.feature:3[0m
[33mGiven [0m[33mMark flew a kite[0m
[33mWhen [0m[33mMark flies a kite on Dec 1st 2015[0m
[33mThen [0m[33mThe kite should fly up[0m
1 Scenarios ([33m1 undefined[0m)
3 Steps ([33m3 undefined[0m)
0m0.000s
You can implement missing steps with the snippets below:
#Given("^Mark flew a kite$")
public void mark_flew_a_kite(String arg1, int arg2, int arg3, int arg4) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^The wind blows (\\d+)st (\\d+)$")
public void the_wind_blows(int arg1, int arg2) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^The kite should fly up$")
public void kite_should_fly(DataTable arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
// For automatic transformation, change DataTable to one of
// List<YourType>, List<List<E>>, List<Map<K,V>> or Map<K,V>.
// E,K,V must be a scalar (String, Integer, Date, enum etc)
throw new PendingException();
}

I just ended up copying the files into a new cucumber java skeleton and using that instead of the old project. I couldn't find any differences between the two projects other than that the skeleton worked and I have no idea where it was configured that my features had to be located in src/main/resources/Features
I did a search for feature and found nothing.
Link to skeleton

Related

How run cucumber using jar?

I have a project with cucumber and maven.
I can run and build my project successfully from Intellij IDEA.
And I can run project from the command line using:
mvn clean test -Dcucumber.options="src/test/resources/features --tags #TEST2"
Now I need to this project from the command line in another machine that does not have IDEA or cucumber installed. I have an idea that I need to create a jar-file and run exactly it from command line.
CucumberTest.java itself:
#RunWith(Cucumber.class)
#CucumberOptions(
monochrome = true,
glue = {"ru.ab.cd.stepDefs", "ru.abcd.tag.stepdefs"},
features = {"src/test/resources/features/"},
tags = {"#TEST1"},
plugin = {"pretty", "html:target/cucumber-html-report"}
)
public class CucumberTest {
}
TestRunner.java, that runs CucumberTest.java. I made this class specifically for being able to run from the command line. I wanted to pass the value for arguments from the command line. But I still don't understand what values should be passed and try to find out by passing
testArguments.
public class TestRunner{
public static void main(String[] args) throws Throwable {
String[] testArguments = {"/BitBucketProjects/abc/src/test/resources/features/smoke/TEST2.feature"};
cucumber.api.cli.Main.main(testArguments);
}
}
Result when I run TestRunner.java. The test itself did not start. All steps are defined, if I run the same test through the CucumberTest.java, everything is successful.
UUUUUUU
1 Scenarios (1 undefined)
7 Steps (7 undefined)
0m0,014s
You can implement missing steps with the snippets below:
#Допустим("^пользователь переходит на страницу авторизации$")
public void пользователь_переходит_на_страницу_авторизации() {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Допустим("^пользователь находится на странице \"([^\"]*)\"$")
public void пользователь_находится_на_странице(String arg1) {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Допустим("^пользователь загружает тестовые данные из json-файла$")
public void пользователь_загружает_тестовые_данные_из_json_файла() {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Допустим("^пользователь авторизуется с ролью \"([^\"]*)\"$")
public void пользователь_авторизуется_с_ролью(String arg1) {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Допустим("^ПРОВЕРКА\\. Ссылка \"([^\"]*)\" отображается на текущей странице$")
public void проверка_Ссылка_отображается_на_текущей_странице(String arg1) {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Допустим("^ПРОВЕРКА\\. Таблица \"([^\"]*)\" отображается на текущей странице$")
public void проверка_Таблица_отображается_на_текущей_странице(String arg1) {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
Process finished with exit code 0
Help!
What parameters should I pass to A in order for the test to run?
I need to use tags as parameters. How to do it?
The error said that cucumber does not see classes with step definition. Changed the class and the error disappeared
public class RunnerTest {
private static String[] defaultOptions = {
"--glue", "ru.ab.cd.stepDefs",
"--glue", "ru.abcd.tag.stepdefs",
"--tags", "#TEST2",
"src/test/resources/features/"
};
public static void main(String[] args) throws Throwable {
Stream<String> cucumberOptions = Stream.concat(Stream.of(defaultOptions), Stream.of(args));
cucumber.api.cli.Main.main(cucumberOptions.toArray(String[]::new));
}
}
"--glue" - a package that contains classes with the implementation
of steps and hooks
"--tags" - a filter for running tests by tags. This line can be deleted and the value passed through the console: --tags #TEST2
"src/test/resources/features/" - the last line that has no prefix like "--keyword" - is the path to the folder with .feature files.
The framework will search for files in this and in all child folders.

Verify whether a method parameter is used in the method body

I have an interface which looks like the following
interface Evaluator {
boolean requiresP2();
EvalResult evaluate(Param1 p1, Param2 p2, Param3 p3);
// some more methods
}
This interface is implemented by several classes. The parameter p2 of the evaluate method is used by some and not used by others. The method requiresP2 basically returns a boolean telling whether the evaluate method uses p2 or not.
Now, this questions may appear a little weird out of context but believe me, it makes sense in our use case. Plus, it would require a lot of time to refactor all the code to eliminate the need for the requiresP2 method so I would appreciate if we discuss solutions other than a top-to-bottom refactoring of the codebase.
The problem is that the return value of method requiresP2 is based on how the evaluate method is implemented. Therefore everyone must ensure that they update the requiresP2 method when they change the evaluate method.
I am looking for ways so that this can be enforced by the compiler/unit-tests/linters rather than leaving it to the developer's memory.
EDIT: I am still exploring the applicability of mocking frameworks to this problem.
I thought that I could reflection in unit tests to inspect evaluate's body in the unit test to check if it refers to p2 or not and then making sure it matches with the value returned by requiresP2 method but it seems that it is not possible to inspect method body using reflection.
I am looking for suggestions on how to do this. Any input is appreciated.
There is another option you did not mention: a Static Code Analysis tool.
You can use the SonarQube + SonarLint combination in order to get your desired enforcement:
Use the SonarQube server in order to create a new static code analysis rule, which will be based on the interface you are using and your unique use case.
Then install SonarLint on your IDE/IDEs (Eclipse and IntelliJ are both supported), and connect it to the SonarQube server.
This way the static code analysis scan will detect improper usage of your interface and indicate this with a visual marking in the IDE, on the relevant code lines (which is actually linting your code).
You can use ASM to check whether the parameter is used.
To add it to your project using e.g. Apache Ivy, you would add this to ivy.xml:
<dependency org="org.ow2.asm" name="asm" rev="6.1.1" />
Or do the equivalent for Maven, Gradle, etc. Then you can check on the parameter by:
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
// . . .
public static boolean usesP2(Evaluator evaluator) {
AtomicBoolean usesP2 = new AtomicBoolean(false);
String internalName = evaluator.getClass().getName().replace('.', '/');
String classFileResource = "/" + internalName + ".class";
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6) {
#Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
if ("evaluate".equals(name)) {
return new MethodVisitor(Opcodes.ASM6) {
#Override
public void visitVarInsn(final int insn, final int slot) {
if (slot == 2) usesP2.set(true);
}
};
}
return super.visitMethod(access, name, desc, signature, exceptions);
}
};
try (InputStream is = Evaluator.class.getResourceAsStream(classFileResource)) {
ClassReader reader = new ClassReader(is);
reader.accept(visitor, 0);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return usesP2.get();
}
public static void assertCorrectlyDocumentsP2(Evaluator evaluator) {
boolean usesP2 = usesP2(evaluator);
if (usesP2 && !evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" uses P2 without documenting it");
}
if (!usesP2 && evaluator.requiresP2()) {
throw new AssertionError(evaluator.getClass().getName() +
" says it uses P2 but does not");
}
}
Unit tests:
#Test
public void testFalsePositive() {
assertCorrectlyDocumentsP2(new FalsePositive());
}
#Test
public static void testFalseNegative() {
assertCorrectlyDocumentsP2(new FalseNegative());
}
(This supposes there are two bad Evaluators, FalsePositive and FalseNegative, one of which documents that it uses P2 but doesn't, and the other which doesn't document that it uses P2 even though it does, respectively.)
Note: In usesP2 we check for a variable instruction (an instruction which accesses a local variable) in slot 2 of the stack frame. The slots are numbered from 0, and the first one is this. P2 is in slots 2 only because Evaluator::evaluate is an instance method. If it were a static method, we would have to check if slot 1 were used in order to detect if parameter P2 were used. Caveat lector.

Stepdefs are not recognized when running but they are recognized when I hover over the steps in .feature file why?

I have viewed the following similar questions and they are not applicable:
Cucumber - implementing missing steps in java
cucumber not able to recognize the implemented methods
also viewed https://github.com/cucumber/cucumber/issues but no hits
I am running Java 1.8 with cucumber, when I hover over the steps in .feature file i can see there implementation but when i run the test i get:
You can implement missing steps with the snippets below:
#Given("^I am on the Login Page$")
public void i_am_on_the_Login_Page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I enter the non existent email$")
public void i_enter_the_non_existent_email() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I enter the false password$")
public void i_enter_the_false_password() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#When("^I click on it$")
public void i_click_on_it() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^I still on the page$")
public void i_still_on_the_page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
I thought may be i did some thing wrong in project configurations but when I also imported the cucumber-java-skeleton from https://github.com/cucumber/cucumber-java-skeleton
when I populate the skelton project with my own implementation as below i get the above same error when i run the test but i still can see the implementation when i hover over steps in .feature file:
#Given("^I am on the Login Page$")
public void i_am_on_the_Login_Page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
}
#When("^I enter the non existent email$")
public void i_enter_the_non_existent_email() throws Throwable {
// Write code here that turns the phrase above into concrete actions
}
#When("^I enter the false password$")
public void i_enter_the_false_password() throws Throwable {
// Write code here that turns the phrase above into concrete actions
}
#When("^I click on it$")
public void i_click_on_it() throws Throwable {
// Write code here that turns the phrase above into concrete actions
}
#Then("^I still on the page$")
public void i_still_on_the_bb() throws Throwable {
// Write code here that turns the phrase above into concrete actions
}
.feature file:
Feature: Login
Scenario: Testing with false credentials
Given I am on the Login Page
When I enter the non existent email
And I enter the false password
And I click on it
Then I still on the page
I am using Netbeans latest version with the same pom.xml file as the skelton project.
I have used tidy Gherkin to get the Gherkin translate into Java code
is there any other way to get Gherkin translated into Java specially Java 8 other than Tidy gherkin?? maybe that is the issue??
Thank you for you help in advance
I am away from my computer so I don't have a way to check this, but have your Gherkin match you method names exactly.

Java - Choosing the design pattern - 2 interfaces with same methods, except one has an extra parameter

So I have 2 interfaces (show below), 1 for regular/free kits and another one for purchasable kits. They both contain 2 methods, but in the "getIcon" method for purchasable kits, I need the player's profile as a parameter so I can check if they have bought the kit.
What is the best design pattern to use to link these 2 interfaces? and can you possibly show me the code to do it?
The 2 interfaces:
public interface Kits {
void giveKit(Player player);
Item getIcon();
}
public interface PurchasableKits {
void giveKit(Player player);
Item getIcon(Profile profile);
}
I attempted to use the adapter pattern but it doesn't seem right because the "getIcon" method is taking in a profile as a parameter but it doesn't get used.
public class KitAdapter implements PurchasableKits {
private Kits kits;
public KitAdapter(Kits kits) {
this.kits = kits;
}
#Override
public void givetKit(Player player){
kits.giveKit(player);
}
#Override
public void getIcon(Profile profile){
kits.getIcon();
}
}
Thanks in advance
You have 1 interface PurchasableKits. A free Kit would implement the interface and call getIcon(null).
The red flag is that the 2 interfaces are almost exactly the same. No design pattern will get you out of the situation that creates.
That's a tricky question because of the rules of the inheritance and cyclic inheritance avoided in java.
I don't believe that you need to interfaces, you could do something like this:
public interface Kits {
void giveKit(Player player);
//a vargars usage
Item getIcon(Profile... p);
}
public class ConcreteClass implements Kits{
#Override
public void giveKit(Player player) {
// TODO Auto-generated method stub
}
#Override
public Item getIcon(Profile... o) {
//This is the ugly thing of this method. You must check the sent params.
//However I think it is better than send a null param, as the clean code suggest to avoid
if(o.length == 0)
System.out.println("without profile");
else
System.out.println("With profile");
return null;
}
}
public class Main {
public static void main(String[] args) {
ConcreteClass my = new ConcreteClass();
my.getIcon();
my.getIcon(new Profile());
}
}
The output:
without profile
With profile
So I have 2 interfaces (show below), 1 for regular/free kits and another one for purchasable kits. They both contain 2 methods, but in the "getIcon" method for purchasable kits, I need the player's profile as a parameter so I can check if they have bought the kit.
Whether or not the profile is needed in the getIcon(...) method is an implementation detail of those Kits that are purchasable. I would just have a Kit interface that has the following definition:
public interface Kit {
void giveKit(Player player);
Item getIcon(Profile profile);
}
So every time you wanted to get the icon you would pass in the Profile and it would be up to the kits that are purchasable to look at the profile. The free ones would just ignore the argument. That you sometimes pass in null and sometimes not means that you know beforehand whether or not it is free which means that something is wrong with your model.
Couple of other comments about your code. Just my opinions:
Concrete classes tend to be nouns. Interfaces tend to be verbs. Maybe KitHandler instead of Kit?
Class names tend to be singular so then you can put them in a list. Maybe Kit (or KitHandler) would be better so you can create a List<Kit> kits = ....
I used get methods to return fields which means that they typically don't take arguments. Maybe getIcon should be generateIcon(...)?

Failed to redefine class When I try to retransform class

I was trying to modify class dynamically, such as call sleep() before a line. I attached agent to a jvm during runtime using Attach method. Then I got target class from jvm, and modified it(Add a line to call sleep()). And I got redine class error. I am using JDK1.6. I am using ASM core API to modify class.
The Error:
Caused by: java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields)
at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
at sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:124)
Is there something wrong with ASM code? Actually my ASM code finished its job(to Add a line to call sleep()). Does current jvm not support retransform class? It seems failed to execute retransformClasses(). Does retransformClasses() not support the ASM operation(to add a line into a method to call sleep())? Any ideas? thx
EDIT:
The class which I want modify:
import java.util.concurrent.TimeUnit;
public class Person {
public String name = "abc";
public String address = "xxxxx" ;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void sayHello() throws InterruptedException {
System.out.println("aaaaaaaaaa");
System.out.println("Hello World!");
TimeUnit.SECONDS.sleep(120);
System.out.println("dd");
}
public void sayHello2() {
System.out.println("aaaaaaaaaa1");
System.out.println("Hello World!2");
}
public static void main (String args[]) {
try {
Person p = new Person();
p.sayHello(); // linenumber #9. A line to call Sleep() should be added before #here.
p.sayHello2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
My ASM code:
public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) {
Label la=new Label();
mv.visitLabel(la);
int linenumber=la.getOffset();
if(linenumber==9) {
mv.visitFieldInsn(Opcodes.GETSTATIC, "java/util/concurrent/TimeUnit", "SECONDS", "Ljava/util/concurrent/TimeUnit;");
mv.visitLdcInsn(new Long("5"));
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/concurrent/TimeUnit", "sleep", "(J)V");
super.visitMethodInsn(arg0, arg1, arg2, arg3);
}
}
Not looking at your code yet, I think I can suggest something. When a class is first loaded, in addition to storing the class's byte codes, the JVM also has tables where it keeps track of the types of fields and the signatures of methods in each class.
The error you are seeing would suggest that the class was loaded, this signature information was stored and then you tried to add the method after that.
If you instead put your agent jar onto the command line, you can do things before the class is loaded for the first time. If you add your method before the signature info is stored away, you should be good.
If you have to connect the agent after the process is already launched, you may be able to transform the class but you may only be able to transform it without changing the set of fields, their types, or the methods, or their signatures. In other words, you may be able to change the byte codes but you have to not invalidate the previously-stored meta information.

Categories