Cucumber 6 + JUnit 5 + Spring Parallel Scenarios Execution - java

I've been reading a lot of documentations, posts, articles and it's said that out-of-box solution to run scenarios in a single feature file in parallel is impossible.
We can use maven-surefire-plugin to run in parallel different feature files, but not scenarios.
For example there is a feature file with scenarios:
Feature: Parallel Scenarios
Scenario: First
...
Scenario: Second
...
Scenario: Third
...
And I'd like to run all there scenarios concurrently in separated threads.
How can I achieve this?

I am using testNG with courgette-jvm to run parallel tests at scenario level
. Here is runner file
import courgette.api.CourgetteOptions;
import courgette.api.CourgetteRunLevel;
import courgette.api.CucumberOptions;
import courgette.api.testng.TestNGCourgette;
import org.testng.annotations.Test;
#Test
#CourgetteOptions(
threads = 10,
runLevel = CourgetteRunLevel.SCENARIO,
rerunFailedScenarios = true,
rerunAttempts = 1,
showTestOutput = true,
reportTitle = "Courgette-JVM Example",
reportTargetDir = "build",
environmentInfo = "browser=chrome; git_branch=master",
cucumberOptions = #CucumberOptions(
features = "src/test/resources/com/test/",
glue = "com.test.stepdefs",
publish = true,
plugin = {
"pretty",
"json:target/cucumber-report/cucumber.json",
"html:target/cucumber-report/cucumber.html"}
))
class AcceptanceIT extends TestNGCourgette {
}
and then use regular webdriver config, I use RemoteWebDriver
protected RemoteWebDriver createDriver() throws MalformedURLException {
//wherever grid hub is pointing. it should work without grid too
String hubURL = "http://localhost:xxxx/wd/hub";
ChromeOptions options = new ChromeOptions();
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, options);
return (RemoteWebDriver) (driver = new RemoteWebDriver(new URL(hubURL), capabilities));
}
public RemoteWebDriver getDriver() throws MalformedURLException {
if (driver == null) {
this.createDriver();
}
return (RemoteWebDriver) driver;
}
you may have to utilize these dependencies
<dependency>
<groupId>io.github.prashant-ramcharan</groupId>
<artifactId>courgette-jvm</artifactId>
<version>5.11.0</version>
</dependency>
<dependency>
<!-- httpclient dpendendecy is to resolve courgette-jvm error - NoClassDefFoundError: org/apache/http/conn/ssl/TrustAllStrategy -->
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-testng</artifactId>
<version>6.9.1</version>
</dependency>

Related

Selenium - Chromeoptions - JsonException

I am a newbie to Automation.Trying to execute below code. Its giving me jsonexception.
I have read on previous answers that desired capabilities is deprecated. I have also tried using chromeoption.merge(capabilities) but even that is not working. Code below. Please help
Exception :
WARNING: Attempt to convert JsonElement from GSON. This functionality is deprecated. Diagnostic stacktrace follows
org.openqa.selenium.json.JsonException: Stack trace to determine cause of warning
public class base {
public WebDriver driver;
public Properties prop;
public WebDriver initializeDriver() throws IOException {
prop = new Properties();
FileInputStream fis = new FileInputStream(
"E:\\SeleniumWorkspace\\E2EProject\\src\\main\\java\\resources\\data.properties");
prop.load(fis);
String browserName = prop.getProperty("browser");
if (browserName.equals("chrome")) {
System.setProperty("webdriver.chrome.driver", "F:\\Setups\\chromedriver_win32Chrome90\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--ignore-ssl-errors=yes");
options.addArguments("--ignore-certificate-errors");
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
}
if (browserName.equals("firefox")) {
driver = new FirefoxDriver();
}
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
return driver;
}
I do not see any issue with your code. However, If I may suggest, you may use the below instead of setting the property each time
To automatically set the property for chrome:
WebDriverManager.chromedriver().setup();
Go here to see for other drivers: WebDriverManager
Now that being said, I think you might be using an old version of Selenium, add the below in your pom.xml
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
<scope>compile</scope>
</dependency>
I am using the above dependencies for running in "headless" mode and my tests do not throw any error for ChromeOptions.

How to write assertTimeoutPreemptively (JUnit 5) in JUnit 4?

Till now I was working on JUnit 5 and now I have to work on an old system with JUnit 4 and I cannot update JUnit 5 there. I have a test in JUnit 5 that I have to write in JUnit 4 but I am not sure how it will work or how to write? Below is the JUnit 5 version of the test.
#AfterEach
void afterEach() throws Exception {
// Bleed off any events that were generated...
assertTimeoutPreemptively(ofMillis(MESSAGE_CLEARING_TIMEOUT_MS), () -> {
boolean tryAgain = true;
while (tryAgain) {
try {
final IMessageFacade message = messageConsumer.receiveMessage(MESSAGE_TIMEOUT_MS);
message.acknowledge();
} catch (MessagingException e) {
tryAgain = false;
}
}
});
broker.stop();
}
In the test, I am using assertTimeoutPreemptively() and am not sure how to convert it to JUnit 4. I tried putting a timeout which is a global timeout in JUnit 4 but that didn't work. Any guidance in terms of writing above #AfterEach condition with JUnit 4?
Shouldn't assertions run only once? Finding asserts in test teardown is somehow surprising. Consider to make your assertions part of your tests.
In JUnit 5 this looks like:
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
public class TimeoutJUnit5Test {
#Test #Timeout(value = 10, unit = MILLISECONDS)
void junitFiveTimeout() {
// ...
}
}
and in JUnit 4:
import org.junit.Test;
public class TimeoutJUnit4Test {
#Test(timeout = 10)
public void junitFourTimeout() {
// ...
}
}
What's stopping you from using both versions of JUnit? (pom.xml):
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
Last option would be to simply copy / adapt the behaviour from the new JUnit 5 assertTimeoutPreemptively() to you own project.

How do I perform BDD test for spring application when am running the the front end using another framework (vuejs) which is running on different port

Am trying to perform BDD tests for my spring application. Am using vuejs for the front end which runs on different port.
My problem is that spring application is failing to connect to the front end application(returns 404 status)
Here is the code on how am connecting to the front end.
import static org.assertj.core.api.Assertions.assertThat;
#ContextConfiguration(classes = MainApplication.class)
#WebAppConfiguration
public class PlantRequestSteps {
List<Plant> plants = new ArrayList<>();
#Autowired
private WebApplicationContext wac;
private WebClient customerBrowser;
HtmlPage customerPage;
#Autowired
PlantHireRepository plantHireRepository;
#Before
public void setUp() {
customerBrowser = MockMvcWebClientBuilder.webAppContextSetup(wac).build();
}
#After
public void tearOff() {
plantHireRepository.deleteAll();
plants.clear();
}
#Given("^the following plants are vailable from this given date$")
public void the_following_plants_are_vailable_from_this_given_date(DataTable table){
for (Map<String, String> row: table.asMaps(String.class, String.class)){
plants.add(Plant.of(
Long.parseLong(row.get("id")), row.get("name"),
row.get("description"), new BigDecimal(row.get("price")),
LocalDate.parse(row.get("date"))));
}
}
#Given("^am on BuildIT's \"([^\"]*)\" web page$")
public void am_on_BuildIT_s_web_page(String arg1) throws Throwable {
customerPage = customerBrowser.getPage("http://localhost:8081/");
}
}
I managed to solve my problem by changing the testing library. Previously I was using HtmlUnit which only works when both the front end and back end are running on the same port(coupled together).
I used selenium and chrome driver which are independent of spring framework
Here is a basic setup ... .....
public class PlantRequestSteps {
#Autowired
private WebApplicationContext wac;
private WebDriver driver ;;
static {
// you should specify the path where you installed your chrome driver
// as the second parameter to this function
System.setProperty("webdriver.chrome.driver", "/path/chromedriver");
}
#Before
public void setup() {
driver = new ChromeDriver();
}
#After
public void tearoff() {
driver.close();
}
#Given("^ that am on this \"([^\"]*)\" web page$")
public void that_am_on_this_web_page(String arg1) throws Throwable {
driver.get("http://localhost:8081/");
}
Also do not forget to add the selenium library in addition to Junit library . Am using maveen so I added mine in the pom.xml file.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.11.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.9.1</version>
<scope>test</scope>
</dependency>
Finally make sure you have the latest version of chrome driver installed(the old version seems not work )

When invoke Java Sparkcontext constructor my Maven web app stops without exceptions or other messages

i have a problem with Maven WebApp with following dependences :
` <dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.10</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.0-rc1</version>
</dependency>
<dependency>
<groupId>org.mongodb.spark</groupId>
<artifactId>mongo-spark-connector_2.10</artifactId>
<version>2.0.0-rc1</version>
</dependency>`
In a EJB (#stateless with local interface, called from a servlet) i have :
public void callSpark(QParams qp){
String uri = "mongodb://localhost:27017/admin.EventCollection";
try {
SparkConf conf = new SparkConf()
.setMaster("local")
.setAppName("BigDataEvent")
.set("spark.mongodb.input.partitioner",
"MongoPaginateBySizePartitioner")
.set("spark.app.id", "BigDataAnalysis")
.set("spark.mongodb.input.uri", uri)
.set("spark.mongodb.output.uri", uri);
JavaSparkContext jsc = new JavaSparkContext(conf);
SparkSession sparkSession = SparkSession.builder().getOrCreate();
SQLContext sqlc = new org.apache.spark.sql.SQLContext(jsc);
Dataset<Row> df = MongoSpark.load(jsc).toDF();
df.createOrReplaceTempView("EventCollection");
postCodeQuery(df,qp); //my method
eventTypeQuery(sparkSession, eventType); //my method
} catch (Exception ex){Logger.getLogger(SparkContext.class.getName()).log(Level.SEVERE, null, ex);
}
This code works very well in a Java Client Maven application but in this situation (Maven Web APP) the application crashes (without exception and error message) when I call :
JavaSparkContext jsc = new JavaSparkContext(conf);
The application make build and deploy (on GlassFish 4.1.1) without errors or exception.
Anyone Had Similar Experiences with this configuration?
Thanks...

Classes not found in maven project despite the library being included in the pom

I'm trying to run this open-source project, rokuality-server (full codebase here: https://github.com/rokuality/rokuality-server).
But in this method below I'm getting a java.lang.NoClassDefFoundError when trying to instantiate any Sikuli classes like Pattern or Finder.
import org.sikuli.script.Finder;
import org.sikuli.script.Image;
import org.sikuli.script.Match;
import org.sikuli.script.Pattern;
#SuppressWarnings("unchecked")
public class ImageUtils {
private static JSONObject getElement(String sessionID, String locator, File screenImage) {
JSONObject element = new JSONObject();
element.put(SessionConstants.ELEMENT_ID, UUID.randomUUID().toString());
boolean isFile = locator != null && new File(locator).exists();
boolean elementFound = false;
if (!screenImage.exists()) {
return null;
}
if (isFile) {
Finder finder = null;
float similarity = Float.valueOf(
SessionManager.getSessionInfo(sessionID).get(SessionConstants.IMAGE_MATCH_SIMILARITY).toString());
Pattern pattern = null;
try {
//******** THIS LINE BELOW THROWS THE ERROR ********
pattern = new Pattern(locator).similar(similarity);
finder = new Finder(screenImage.getAbsolutePath());
} catch (Exception e) {
Log.getRootLogger().warn(e);
}
}
// more code here
}
}
My suspicion is that something in the pom.xml file is wrong, so here's the Sikuli X Api dependency as it appears there:
<dependency>
<groupId>com.sikulix</groupId>
<artifactId>sikulixapi</artifactId>
<version>1.1.2</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
</exclusion>
<exclusion>
<groupId>com.github.vidstige</groupId>
<artifactId>jadb</artifactId>
</exclusion>
<exclusion>
<groupId>com.sikulix</groupId>
<artifactId>sikulix2tigervnc</artifactId>
</exclusion>
</exclusions>
</dependency>
I tried changing the version to the latest one, 2.0.0 but it caused some errors in the project, which I think are related to changes in the org.sikuli.script.Image class's methods. Do I maybe need an earlier version?
This should be fixed in the newer releases of the rokuality project:
https://github.com/rokuality/rokuality-server/releases. It depended on the java jdk version the user was running.

Categories

Resources