IntelliJ cannot find Step Definitions from Feature File - java

I've setup the following cucumber skeleton project using the repo from Cucumber:
https://github.com/cucumber/cucumber-java-skeleton
I'm using IntelliJ 2019.1.3 with the latest bundled Cucumber for Java and Gherkin plugins
I'm using Java: openjdk version "1.8.0_232"
I'm have a local Gradle install of 6.0.1 and for the project, gradlew 6.7.1
I have the following cucumber dependencies specified:
testImplementation 'io.cucumber:cucumber-java:6.9.1'
testImplementation 'io.cucumber:cucumber-junit:6.9.1'
When I run using the command line:
./gradlew test --rerun-tasks --info
...the tests can be run from the RunCucumberTest JUnit runner, but I cannot configure the bundled Cucumber and Gherkin plugins to 'see' the Steps from the Feature File as they all remain grayed out:
Given I'm using Cucumber's own vanilla project, what can I try to resolve the issue of the Feature File failing to recognised or run the steps?

Well as the error you are getting says:
io.cucumber.skeleton.RunCucumberTest > Belly.a few cukes FAILED
io.cucumber.junit.UndefinedStepException: The step "I wait 1 hour" is >undefined. You can implement it using the snippet(s) below:
So add the following snippet into StepDefinitions.java file:
#When("I wait {int} hour")
public void i_wait_hour(Integer int1) {
// Write code here that turns the phrase above into concrete actions
throw new io.cucumber.java.PendingException();
}

Related

How can I run Cucumber Test runner from CLI without using Maven

I have seen the posts -
How to run cucumber file from command line
Cucumber java project without maven - how to run from command prompt if i am having Runner class
But the solutions given there are not very clear.
My CucumberRunner.java looks like -
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/test/resources/features",
tags="#Regression",
monochrome = false,
plugin = {"pretty",
"com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:",
"timeline:test-output-thread/",
"json:target/cucumber-reports/jsonReports/Cucumber.json",
"html:target/cucumber-reports/Cucumber.html"}
)
public class CucumberRunner {
}
Unfortunately because of security reasons I can not install maven on Linux machine. So I want to run this CucumberRunner file from CLI.
As suggested in the previous posts I tried below in my Cucumber class
public class CucumberRunner {
public static void main(String[] args){
Main.main(new String[]{"-g", "src/test/java/stepdefinitions", "src/test/resources/features/Validate.feature"});
}
}
But it gives me exception
Exception in thread "main" java.lang.NoClassDefFoundError: io/cucumber/core/cli/Main
at CucumberRunner.main(CucumberRunner.java:29)
Caused by: java.lang.ClassNotFoundException: io.cucumber.core.cli.Main
at java.net.URLClassLoader.findClass(URLClassLoader.java:387)
at java.lang.ClassLoader.loadClass(ClassLoader.java:419)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
at java.lang.ClassLoader.loadClass(ClassLoader.java:352)
... 1 more
But This also doesn't give any solution to run on the basis of Cucumber tags.
Any solution or pointer is appreciated.
Kind Regards,
Abhi
In order to run a Java application, you need to be able to resolve ALL dependencies at runtime. This means that, every single library referenced on the POM under the dependencies tag, must be somewhere in the machine where Selenium (Cucumber) is running. Likewise, if those libraries have dependencies of their own, you must also download them somewhere in the machine.
You have a few choices to access the dependent libraries. You need to reference all dependencies as external JARs (reside outside your application JAR) or you need to package them inside your application JAR. You can use a build tool like ANT to build your JAR and map your dependencies similar to how is done in Maven. Obviously the difference is that you need to do what I described before (your build tool will need to know where these JARs are physically located).
To execute, you will obviously need a main method. Because this is using Selenium (Cucumber), your Runner class is ran by JUnit or TestNG (depending on what you are using). After that, the rest is up to you. For example, you could simply create a batch file to launch your application, or you could use a tool like Launch4J to create an executable. Of course, the latter required creating an executable JAR.

Junit Jupiter 5 (Intellij) Not recognizing import org.junit.jupiter.api.Test Class

I created a simple java app using gradle init. I am using Intellij 2021.2.2.
When i build the project i am getting following.
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java application project to get you started.
* For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
* User Manual available at https://docs.gradle.org/7.2/userguide/building_java_projects.html
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
id 'application'
id 'java'
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.5.2')
}
application {
// Define the main class for the application.
mainClass = 'JunitPOC.App'
}
test{
useJUnitPlatform()
}
tasks.named('test') {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
Looking into the dependencies i can see that all the dependencies are in the test compile & runtime path.
Looking a bit deeper into the sources i found that Intellij is not picking up the source file for junit.api jar just for Test Class correctly. All the other classes i can refer to.
Has anybody run into this issue? Any help would be appriciated.
I was able to make it working after going into FILE > Manage IDE Settings > Restore Default Settings.

Run Dynamodb local as part of a Gradle Java project

I am trying to run DynamoDB local for testing purposes. I followed the steps amazon provides for setting it up and running the jar by itself works fine (link to amazon's tutorial Here). However, the tutorial doesn't go over running the jar within your own project. I don't want all the other developers to have to grab a jar and run it locally every time they test their code.
That is where my question comes in. I've had a real hard time finding any examples online of how to configure a Gradle project to run the DynamoDB local server as part of my tests. I found the following maven example https://github.com/awslabs/aws-dynamodb-examples/blob/master/src/test/java/com/amazonaws/services/dynamodbv2/DynamoDBLocalFixture.java#L32 and am trying to convert it to a Gradle, but am getting errors for all of com.amazonaws.services.dynamodbv2.local import statements they are using. The errors are that the resource cannot be found.
I went into their project's pom and put the following into my build.gradle file to emulate it.
//dynamodb local dependencies
testCompile('com.amazonaws:aws-java-sdk-dynamodb:1.10.42')
testCompile('com.amazonaws:aws-java-sdk-cloudwatch:1.10.42')
testCompile('com.amazonaws:aws-java-sdk:1.3.0')
testCompile('com.amazonaws:amazon-kinesis-client:1.6.1')
testCompile('com.amazonaws:amazon-kinesis-connectors:1.1.1')
testCompile('com.amazonaws:dynamodb-streams-kinesis-adapter:1.0.2')
testCompile('com.amazonaws:DynamoDBLocal:1.10.5.1')
The import statements still fail. Here is an example of one that fails.
import com.amazonaws.services.dynamodbv2.local.embedded.DynamoDBEmbedded;
TL;DR
Has anyone managed to get the DynamoDB local JAR to execute as part of a Gradle project or have a link to a good tutorial (it doesn't have to be the tutorial I linked to).
We have DynamoDB local working with gradle. Here's what you need to add to your gradle.build file:
For gradle 4.x and below versions
1) Add to the repositories section:
maven {
url 'http://dynamodb-local.s3-website-us-west-2.amazonaws.com/release'
}
2) Add to the dependencies section (assuming you're using this for your tests):
testCompile group: 'com.amazonaws', name: 'DynamoDBLocal', version: 1.11.0
3) These next two steps are the tricky part. First copy the native files to a directory:
task copyNativeDeps(type: Copy) {
from (configurations.testCompile) {
include "*.dylib"
include "*.so"
include "*.dll"
}
into 'build/libs'
}
4) Then make sure you include this directory (build/libs in our case) in the java library path like so:
test.dependsOn copyNativeDeps
test.doFirst {
systemProperty "java.library.path", 'build/libs'
}
Now you should be able to run ./gradlew test and have your tests hit your local DynamoDB.
For Gradle 5.x the below solution works
maven {
url 'http://dynamodb-local.s3-website-us-west-2.amazonaws.com/release'
}
configurations {
dynamodb
}
dependencies {
testImplementation 'com.amazonaws:DynamoDBLocal:1.11.477'
dynamodb fileTree (dir: 'lib', include: ["*.dylib", "*.so", "*.dll"])
dynamodb 'com.amazonaws:DynamoDBLocal:1.11.477'
}
task copyNativeDeps(type: Copy) {
from configurations.dynamodb
into "$project.buildDir/libs/"
}
test.dependsOn copyNativeDeps
test.doFirst {
systemProperty "java.library.path", 'build/libs'
}
I run into the same problem and first I tried to add sqlite4java.library.path to the Gradle script as it has been mentioned in the other comments.
This worked for command line, but were not working when I was running the tests from IDE (IntelliJ IDEA), so finally I come up with a simple init method, that is called at the beginning of each of integration tests:
AwsDynamoDbLocalTestUtils.initSqLite();
AmazonDynamoDBLocal amazonDynamoDBLocal = DynamoDBEmbedded.create();
Implementation can be found here: https://github.com/redskap/aws-dynamodb-java-example-local-testing/blob/master/src/test/java/io/redskap/java/aws/dynamodb/example/local/testing/AwsDynamoDbLocalTestUtils.java
I put a whole example to GitHub, it might be helpful: https://github.com/redskap/aws-dynamodb-java-example-local-testing
In August 2018 Amazon announced new Docker image with Amazon DynamoDB Local onboard. It does not require downloading and running any JARs as well as adding using third-party OS-specific binaries like sqlite4java.
It is as simple as starting a Docker container before the tests:
docker run -p 8000:8000 amazon/dynamodb-local
You can do that manually for local development, as described above, or use it in your CI pipeline. Many CI services provide an ability to start additional containers during the pipeline that can provide dependencies for your tests. Here is an example for Gitlab CI/CD:
test:
stage: test
image: openjdk:8-alpine
services:
- name: amazon/dynamodb-local
alias: dynamodb-local
script:
- ./gradlew clean test
So, during the test task DynamoDB will be available on http://dynamodb-local:8000.
Another, more powerful tool is localstack. It supports two dozen of AWS services, DynamoDB is one of them. The isage is very similar, you have to start it before running the tests and it will expose AWS-compatible APIs on given ports:
test:
stage: test
image: openjdk:8-alpine
services:
- name: localstack/localstack
alias: localstack
script:
- ./gradlew clean test
The idea is to move all the configuration out of your build tool and tests and provide the dependency externally. Think of it as of dependency injection / IoC but for the whole service, not just a single bean. This way, you code is more clean and maintainable. You can see that even in the examples above: you can switch mock implementation from DynamoDB Local to localstack by simply changing the image part!
The easiest way, in my opinion, is to:
Download the JAR from here:
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html#DynamoDBLocal.DownloadingAndRunning
Then unzip the downloaded folder and add its content to the /libs folder in the project (create the /libs folder before that)
Finally, add to the build.gradle:
dependencies {
runtime files('libs/DynamoDBLocal.jar')
}
I didn't want to create a specific configuration for dynamo for gradle 6+ so I tweaked the original answer instructions. Also, this is in kotlin gradle DSL rather than groovy.
val copyNativeDeps by tasks.creating(Copy::class) {
from(configurations.testRuntimeClasspath) {
include("*.dylib")
include("*.so")
include("*.dll")
}
into("$buildDir/libs")
}
tasks.withType<Test> {
dependsOn.add(copyNativeDeps)
doFirst { systemProperty("java.library.path", "$buildDir/libs") }
}
By leveraging the testRuntimeClasspath configuration, gradle is able to locate the relevant files for you without needing to create a custom configuration. Obviously this has the side effect that if your test runtime has many native deps, they will also be copied which would make the custom configuration approach more ideal.

How to run single Android local unit test using gradle 2.4. Test filtering is not supported

I'm using gradle to build my android project and am not able to run single local unit test. I have several test classes and one of them is MockServerTest and I only want to run test methods in this class.
I tried using gradle -Dtest.single=MockServerTest test but it turned out running all my tests, including these in other test classes.
I also tried gradle test --tests MockServerTest but an error occurred said
Test filtering is not supported for given version of junit. Please upgrade junit version to at least 4.6.
But I'm using junit 4.12 in my gradle file
testCompile 'junit:junit:4.12'
I'm using gradle 2.4 with com.android.tools.build:gradle:1.2.3.
Also, how can I run a single test method inside a single test class?
BTW, I'm able to run single test method inside Android Studio, by right clicking on the test method and select run targetTestMethod() from the menu. But how can I achieve this in the terminal? I guess Android Studio also trigger a certain command to do this. How can I see what that command is?
Figured it out myself. I have to run
gradle testDebug --tests com.my.package.TestClassName
There are two things to note here.
1. You have to use gradle testDebug or gradle testRelease instead of just gradle test. If you have build variant, you have to use gradle testVariantNameDebug or gradle testVariantNameRelease
2. You have to specify the whole qualified class name, means including the package name.
You can use Android Gradle plugin DSL to set up test tasks filters like this:
android {
testOptions {
unitTests.all {
it.testNameIncludePattern = "*.SomeTest"
}
}
}
You can find more information on testOptions here and filters here.
Have you tried running gradle test -Dtest.single=MockServerTest? More information can be found here.

How to make Gradle compile Groovy tests before Java tests

The Groovy plugin for Gradle claims that it "supports joint compilation, which allows to freely mix and match Groovy and Java code, with dependencies in both directions".
However, I don't think this applies to test code.
I have a Java 'sample' test in src/test/java... which uses a class which is located in src/test/groovy.
When trying to build with Gradle, I get an error like this:
SwingJavaFXSampleAppTestInJava.java:23: error: cannot find symbol
SwingJavaFXSampleAppTest swingJavaFx = new SwingJavaFXSampleAppTest();
Notice that SwingJavaFXSampleAppTest is a Groovy class that has not been compiled yet (in the Gradle output I can see that it did not run the compileTestGroovy before it tried compileTestJava because the former depends on the latter).
I am able to build this same project with Maven using the groovy-eclipse plugin.
Why does it not work in Gradle when it claims to support compilation in any order, and how can I make it work?
As explained in the Gradle User Guide, only code passed to GroovyCompile tasks is joint-compiled. So either you put both Java and Groovy code into src/main/groovy, or you reconfigure the source sets:
sourceSets.main.java.srcDirs = []
sourceSets.main.groovy.srcDirs = ["src/main/java", "src/main/groovy"]
For tests, replace all occurrences of main with test.
You should be able to move your java tests into src/test/groovy.

Categories

Resources