Cucumber not executing both the features with created stepdefinations
I have tried with tag, also given both full path of both the features but still the same
package runners;
import com.cucumber.listener.ExtentProperties;
import com.cucumber.listener.Reporter;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import managers.Common;
import managers.FileReader;
import org.apache.log4j.PropertyConfigurator;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import java.io.File;
#RunWith(Cucumber.class)
#CucumberOptions(
features = ".//src//test//java//FeatureList",glue = "stepDefinations",
plugin = { "com.cucumber.listener.ExtentCucumberFormatter:",
"junit:target/cucumber-results.xml"},
tags={"#API"},
monochrome = true
)
public class TestRunner {
static String ReportName= Common.ReportName();
#BeforeClass
public static void setup() {
ExtentProperties extentProperties = ExtentProperties.INSTANCE;
extentProperties.setReportPath("target/cucumber-reports/"+ReportName+".html");
PropertyConfigurator.configure(".//src//log4j.properties");
}
#AfterClass
public static void writeExtentReport() {
Reporter.loadXMLConfig(new File(FileReader.getInstance().getConfigReader().getReportConfigPath()));
Reporter.setSystemInfo("User Name", System.getProperty("user.name"));
Reporter.setSystemInfo("Time Zone", System.getProperty("user.timezone"));
Reporter.setSystemInfo("Environment", FileReader.getInstance().getConfigReader().getEnvironment());
}
}
Not sure why its always running error codes.feature but never enums.feature
Feature: Enums Codes
#API
Scenario: xxx Enums Codes
Given Run get method "xxxxxxxxxxx" api to get fetch all type of xxx xxx
Then response should be 200
And xxxxxxxxxxxxxx
Feature: Error Codes
#API
Scenario: xxError Codes
Given Run "xxxx" api to get response
Then response should be 200
And Verify xx Error Codes xx error response
"features" is looking for a filesystem path:
features = ".//src//test//java//FeatureList"
Try this -
1 features = "src/test/java/FeatureList"
2 features = "FeatureList"
Related
Been trying to learn/perform some automated testing using Selenium + JUnit + Cucumber and I've spent hours browsing through the internet trying to resolve this with no success. I've written my feature, steps and runner code and the 'glue' is mapped to the correct package too. However, I run into the topic error when I try to run my Runner.java file.
Project Structure
Feature file:
Feature: Admin login
Scenario: Logging into Fleet Portal
Given user navigates to Fleet Portal
When enter credentials
Then user had logged
Runner file:
package Runner;
import org.junit.runner.RunWith;
import io.cucumber.junit.*;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "Features"
,glue="Steps"
)
public class TestRunner {}
Step file:
package Steps;
import java.util.ArrayList;
import java.util.Scanner;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
class App {
private static final WebDriver driver = new ChromeDriver();
public void myMethod(String flag) {
System.out.println(flag);
}
#Given("user navigates to Fleet Portal")
public void user_navigates_to_fleet_portal() {
throw new io.cucumber.java.PendingException();
}
#When("enter credentials")
public void enter_credentials() throws InterruptedException {
throw new io.cucumber.java.PendingException();
}
#Then("user had logged in successfully")
public void user_had_logged_in_successfully() {
myMethod("yes");
throw new io.cucumber.java.PendingException();
}
}
I've tried to take JUnit out of the picture by simply running the feature file as a cucumber test but it still results in the same error, which is weird because the cucumber plugin confirms that the steps are mapped to the features -> feature mapping
POM file
Any and all help is appreciated.
I know how to use two runner classes to rerun failed scenarios, but I want this feature only for one test.
Let's say that I have 100 scenarios and I only want to rerun scenario 40 when it fails, but if any other scenaria fails, I don't want it to rerun. Is there a way to implement this for one test in particular?
To see how to rerun all failed scenarios, check out this question:
How to rerun the failed scenarios using Cucumber?
You'll have to write custom code for this. Fortunately this is relatively easy with the JUnit Platform API (JUnit 5).
https://github.com/cucumber/cucumber-jvm/tree/main/cucumber-junit-platform-engine#rerunning-failed-scenarios
package com.example;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.engine.discovery.UniqueIdSelector;
import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;
import org.junit.platform.launcher.listeners.TestExecutionSummary.Failure;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectDirectory;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
public class RunCucumber {
public static void main(String[] args) {
LauncherDiscoveryRequest request = request()
.selectors(
selectDirectory("path/to/features")
)
.build();
Launcher launcher = LauncherFactory.create();
SummaryGeneratingListener listener = new SummaryGeneratingListener();
launcher.registerTestExecutionListeners(listener);
launcher.execute(request);
TestExecutionSummary summary = listener.getSummary();
// Do something with summary
List<UniqueIdSelector> failures = summary.getFailures().stream()
.map(Failure::getTestIdentifier)
.filter(TestIdentifier::isTest)
// Filter more to select scenarios to rerun
.map(TestIdentifier::getUniqueId)
.map(DiscoverySelectors::selectUniqueId)
.collect(Collectors.toList());
LauncherDiscoveryRequest rerunRequest = request()
.selectors(failures)
.build();
launcher.execute(rerunRequest);
TestExecutionSummary rerunSummary = listener.getSummary();
// Do something with rerunSummary
}
}
I'm running into some issues handling a file upload using spring's reactive framework. I think I'm following the docs, but can't get away from this 415 / Unsupported Media Type issue.
My controller looks like below (as per the example here: https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html#webflux-multipart-forms)
package com.test.controllers;
import reactor.core.publisher.Flux;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class TestController {
#RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> uploadHandler(#RequestBody Flux<Part> parts) {
return parts
.filter(part -> part instanceof FilePart)
.ofType(FilePart.class)
.log()
.flatMap(p -> Flux.just(p.filename()));
}
}
POSTing to this endpoint though, always gives me the same output:
curl -X POST -F "data=#basic.ppt" http://localhost:8080/upload
---
"Unsupported Media Type","message":"Content type 'multipart/form-data;boundary=------------------------537139718d79303c;charset=UTF-8' not supported"
I've attempted to use #RequestPart("data") too, but get a similar Unsupported Media Type error, albeit with the content type of the file.
It seems that Spring is having issues converting these to a Part..? I'm stuck - any help is apprecitated!
Well, it's not a direct answer for your question, because I use functional endpoints, but I hope it will help you somehow.
import org.springframework.context.annotation.Bean;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.stereotype.Controller;
import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import java.io.File;
import java.util.Map;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
import static org.springframework.web.reactive.function.server.RequestPredicates.POST;
import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.nest;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
#Controller
public class FileUploadController {
#Bean
RouterFunction<ServerResponse> apiRoutes() {
return nest(path("/api"),
route(POST("/upload"), fileUpload()));
}
private HandlerFunction<ServerResponse> fileUpload() {
return request -> {
return request.body(BodyExtractors.toMultipartData()).flatMap(parts -> {
Map<String, Part> map = parts.toSingleValueMap();
final FilePart filePart = (FilePart) map.get("file");
final String dir = "C:\\JDeveloper\\mywork\\Spring\\SpringTest\\webflux-file-upload\\uploaded";
filePart.transferTo(new File(dir + "/" + filePart.filename()));
return ServerResponse.ok().body(fromObject("ok, file uploaded"));
}
);
};
}
}
You can upload a file with curl like this:
curl -F "file=#C:\Users\Wojtek\Desktop\img-5081775796112008742.jpg" localhost:8080/api/fileupload
Thanks #kojot for your answer, but in this case I discovered the issue was my inclusion of spring-webmvc transiently in addition to spring-webflux. Your solution would likely have worked too, but I wanted to stick with the Controller style so ended up forcibly excluding spring-webmvc from my build.gradle:
configurations {
implementation {
exclude group: 'org.springframework', module: 'spring-webmvc'
}
}
After that it worked as documented.
while creating pact verification test i am using httpTarget Method. but the problem is my service dont have a port value. how can we run this? please advise.
Service URL=http://services.groupkt.com/country/get/iso3code/IND
below is my verification test.
package se.ff.bsv;
import au.com.dius.pact.provider.junit.PactRunner;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.State;
import au.com.dius.pact.provider.junit.loader.PactFolder;
import au.com.dius.pact.provider.junit.loader.PactUrl;
import au.com.dius.pact.provider.junit.target.HttpTarget;
import au.com.dius.pact.provider.junit.target.Target;
import au.com.dius.pact.provider.junit.target.TestTarget;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.runner.RunWith;
import java.net.URL;
import java.util.Map;
#RunWith(PactRunner.class) // Say JUnit to run tests with custom Runner
#Provider("getCountryService") // Set up name of tested provider
#PactFolder("../pacts") // Point where to find pacts (See also section Pacts source in documentation)
//#PactUrl(urls = {"http://services.groupkt.com/country/get/iso3code/IND"} )
public class getCountryContractTest {
#State("There is a country with alpha2_code as IN having name as India") // Method will be run before testing
// interactions that require "with-data"
// state
public void hammerSmith() {
System.out.println("There is a country with alpha2_code as IN having name as India");
}
#TestTarget // Annotation denotes Target that will be used for tests
//public final Target target = new HttpTarget(8111);// Out-of-the-box implementation of Target (for more information take a look at Test Target section)
public final Target target = new HttpTarget("http", "services.groupkt.com",);
}
You can't say your service don't have a port, but you can say your service uses a default port (for instance). In that case, try to use port 80.
I'm new with cucumber and learned this doc carefully to understand how could I implement my first cucumber java project. I have done a lot of analysis and gone through almost all the articles related to it over internet, why its not picking up step definition but could not find the cause. However, everything seems to be OK as per my understanding, I have great expectation that you guys can find my fault at one go.
Looking forward for a +ve response.
Hence I'm sharing the code, message(on console window) and folder structure.
Thanks
Rafi
Feature file:
#MyApplication
Feature: Post text Hello Rafi on Rafi facebook account
Scenario: Login successfully on Facebook application
Given Open Facebook application
When Enter valid id and password
And Click on Login button
Then Facebook home page should open
TestRunner class:
package test.java.runner;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
//glue = {"helpers", "src.test.java.steps"},
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src/features"},
glue = {"helpers", "src.test.java.steps"},
plugin = {"pretty","html:target/cucumber-html-report"},
dryRun = true,
monochrome = true,
tags="#MyApplication",
strict=false)
public class TestRunner {
}
StepDefinition class:
package test.java.steps;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class StepDefinition {
private static WebDriver driver = null ;
private static String password = "*********";
WebDriverWait wait=new WebDriverWait(driver, 30);
WebElement waitElement;
#BeforeClass
public void setup() throws Throwable
{
System.setProperty("webdriver.gecko.driver", "C:\\Selenium Automation\\selenium\\Selenium 3 and Firefox Geckodriver\\geckodriver.exe");
driver = new FirefoxDriver ();
driver.manage().window().maximize();
}
#AfterClass
public void teardown() throws Throwable
{driver.quit();}
// First scenario
#Given("^Open Facebook application$")
public void open_Facebook_application() throws Throwable{
System.out.println("this is not working");
driver.navigate().to("https://www.facebook.com/");
}
#When("^Enter valid id and password$")
public void enter_valid_id_and_password() throws Throwable{
driver.findElement(By.name("email")).clear();
driver.findElement(By.name("email")).sendKeys("rafiras16#gmail.com");
driver.findElement(By.name("pass")).clear();
driver.findElement(By.name("pass")).sendKeys(password);
}
#When("^Click on Login button$")
public void click_on_Login_button() throws Throwable {
driver.findElement(By.xpath("//input[starts-with(#id,'u_0')]")).click();
}
#Then("^Facebook home page should open$")
public void facebook_home_page_should_open() throws Throwable{
String strTitle = driver.getTitle();
System.out.print(strTitle);
}
}
image for message on console window and folder structure
BuildPath details
I think the glue attribute on the CucumberOptions class is wrong. If you want to refer to the step definitions using the file path then you need to change that to:
glue = {"helpers", "src/test/java/steps"},
If you want to refer them by package then you need to remove the "src." prefix:
glue = {"helpers", "test.java.steps"},
Try changing,
glue = {"helpers", "src.test.java.steps"}
to
glue = {"test.java.steps"}
And what is this helpers package i don't see it in the screenshot.
The #AfterClass and #BeforeClass annotations are useful only if the class is a junit test class. You have placed them in a normal class, thus they will not be run. This leads to the driver remaining uninitaialized.
The easy way out is to use the cucumber #Before and #After annotation. Change the #BeforeClass to #Before and #AfterClass to #After.