Skip to content
This repository was archived by the owner on Mar 18, 2019. It is now read-only.

Generic reruner #89

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>1.2.5</version>
</dependency>
</dependencies>

<dependencyManagement>
Expand Down
42 changes: 42 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ Usage
Add the following to your POM file:

```xml
<dependency>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>3.3.0</version>
</dependency>


<plugin>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
Expand Down Expand Up @@ -57,6 +69,8 @@ Add the following to your POM file:
<customVmTemplate>src/test/resources/cucumber-custom-runner.vm</customVmTemplate>
<!-- Specify a custom package name for generated sources. Default is no package.-->
<packageName></packageName>
<!-- Specify count from 1 to 5 to enable re-run functionality, by default it is 0 if not specified-->
<retryCount>0</retryCount>
</configuration>
</execution>
</executions>
Expand Down Expand Up @@ -105,6 +119,34 @@ It is up to you to ensure that class names generated are valid and there are no

The `namingPattern` property is for the **class name** only. Do not add the `.java` suffix.

###Re-Run Functionality

* **Why it's bad to keep re-running more than 1 or more time ?**
When we run test cases first time, we got some failure due to environment issues or network issues or grid management issues or Browsers issues such test cases we do not considering as **Flaky**, but if we are running again and again and getting same failure result on each run such test cases considered as Flaky, It is useless to keep re-running such test cases, Hence with the help of this plugin you can try only max 5 time.

* **What it does?**
It re-run only failed test cases on each run and after complete run it generate consolidated report.

![alt tag](https://cloud.githubusercontent.com/assets/4283293/15507135/ecb4db80-218f-11e6-97e8-be95413bda86.png)

* **How to enable it?:**
specify retryCount property counts between 1 to 5. `<retryCount>1</retryCount>`

* **Dependency required for this functionality:**
```
<!-- Required for ExtendedRuntimeOption, if user executing by mvn command which avoids resetting of mvn parameters.-->
<dependency>
<groupId>com.github.temyers</groupId>
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
<version>same version of this plugin</version>
</dependency>
<!-- Required for generating consolidate reports of all run at one place-->
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>3.3.0</version>
</dependency>
```

FAQ
===
Expand Down
70 changes: 70 additions & 0 deletions src/it/generic/generic-re-runner/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.github.temyers.it</groupId>
<artifactId>simple-it</artifactId>
<version>1.0-SNAPSHOT</version>

<description>A simple IT verifying the basic use case.</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.version>1.2.2</cucumber.version>
</properties>

<dependencies>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-core</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>net.masterthought</groupId>
<artifactId>cucumber-reporting</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>@project.groupId@</groupId>
<artifactId>@project.artifactId@</artifactId>
<version>@project.version@</version>
<executions>
<execution>
<id>generateRunners</id>
<phase>generate-test-sources</phase>
<goals>
<goal>generateRunners</goal>
</goals>
<configuration>
<glue>com.foo.bar</glue>
<tags>"@complete,@accepted"</tags>
<parallelScheme>SCENARIO</parallelScheme>
<retryCount>1</retryCount>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
Feature: Feature1

@complete
Scenario: Generate Junit Runner for each feature file
Given I have feature files
When I generate Maven sources
Then the file "target/generated-test-sources/1IT.java" should exist
And it should contain:
"""
import com.github.timm.cucumber.options.ExtendedRuntimeOptions;
import cucumber.runtime.Runtime;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoaderClassFinder;
import net.masterthought.cucumber.ReportBuilder;
import org.apache.commons.io.FileUtils;
import org.junit.Test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


public class Parallel01IT {

private String outputPath = "target/cucumber-parallel/Parallel01IT/Parallel01IT";

@Test
public void reRun() {

defaultRun();

switch (1) {
case 1:
firstRun();
break;
case 2:
firstRun();
secondRun();
break;
case 3:
firstRun();
secondRun();
thirdRun();
break;
case 4:
firstRun();
secondRun();
thirdRun();
fourthRun();
break;
case 5:
firstRun();
secondRun();
thirdRun();
fourthRun();
fifthRun();
break;
default:
break;
}
generateAllRunReports();

}

private void defaultRun() {
List<String> arguments = new ArrayList<String>();
arguments.add("${feature1.absolutePath}:4");
arguments.add("--plugin");
arguments.add("html:target/cucumber-parallel/Parallel01IT/Parallel01IT.html");
arguments.add("--plugin");
arguments.add("json:target/cucumber-parallel/Parallel01IT/Parallel01IT.json");
arguments.add("--plugin");
arguments.add("rerun:target/cucumber-parallel/Parallel01IT/Parallel01IT.txt");
arguments.add("--glue");
arguments.add("foo,bar");
final String[] argv = arguments.toArray(new String[0]);
try {
executeCLIMain(argv);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public void firstRun() {
try {
if (new File(outputPath + ".txt").exists() && new BufferedReader(new FileReader(outputPath + ".txt")).readLine() != null) {
//executeReRerun first arg: refactored input file ; second arg:- output json file path for getting result
executeReRerun("@" + outputPath + ".txt", outputPath + "/cucumber1.json", outputPath + "/rerun1.txt");
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void secondRun() {
try {
if (new File(outputPath + "/rerun1.txt").exists() && new BufferedReader(new FileReader(outputPath + "/rerun1.txt")).readLine() != null) {
//executeReRerun first arg: refactored input file ; second arg:- output json file path for getting result
executeReRerun("@" + outputPath + "/rerun1.txt", outputPath + "/cucumber2.json", outputPath + "/rerun2.txt");
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void thirdRun() {
try {
if (new File(outputPath + "/rerun2.txt").exists() && new BufferedReader(new FileReader(outputPath + "/rerun2.txt")).readLine() != null) {
//executeReRerun first arg: refactored input file ; second arg:- output json file path for getting result
executeReRerun("@" + outputPath + "/rerun2.txt", outputPath + "/cucumber3.json", outputPath + "/rerun3.txt");
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void fourthRun() {
try {
if (new File(outputPath + "/rerun3.txt").exists() && new BufferedReader(new FileReader(outputPath + "/rerun3.txt")).readLine() != null) {
//executeReRerun first arg: refactored input file ; second arg:- output json file path for getting result
executeReRerun("@" + outputPath + "/rerun3.txt", outputPath + "/cucumber4.json", outputPath + "/rerun4.txt");
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void fifthRun() {
try {
if (new File(outputPath + "/rerun4.txt").exists() && new BufferedReader(new FileReader(outputPath + "/rerun4.txt")).readLine() != null) {
//executeReRerun first arg: refactored input file ; second arg:- output json file path for getting result
executeReRerun("@" + outputPath + "/rerun4.txt", outputPath + "/cucumber5.json", outputPath + "/rerun5.txt");
}
} catch (Exception e) {
e.printStackTrace();
}
}

public void executeReRerun(String rerunFile, String targetJson, String targetRerun) {
List<String> arguments = new ArrayList<String>();
arguments.add(rerunFile);
arguments.add("--plugin");
arguments.add("pretty:" + outputPath + "/cucumber-pretty.txt");
arguments.add("--plugin");
arguments.add("json:" + targetJson);
arguments.add("--plugin");
arguments.add("rerun:" + targetRerun);
arguments.add("--glue");
arguments.add("foo, bar");
final String[] argv = arguments.toArray(new String[0]);
try {
executeCLIMain(argv);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}


public byte executeCLIMain(final String[] argv) throws InterruptedException, IOException {
ExtendedRuntimeOptions runtimeOptions = new ExtendedRuntimeOptions(new ArrayList(Arrays.asList(argv)));
MultiLoader resourceLoader = new MultiLoader(this.getClass().getClassLoader());
ResourceLoaderClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, this.getClass().getClassLoader());
Runtime runtime = new Runtime(resourceLoader, classFinder, this.getClass().getClassLoader(), runtimeOptions);
runtime.run();
System.out.println(runtime.exitStatus());
return runtime.exitStatus();

}

public static void generateAllRunReports() {

try {
List<File> jsons = finder("target/cucumber-parallel/");
List<File> defaultRunJSONs = new ArrayList<File>();
List<File> firstRunJSONs = new ArrayList<File>();
List<File> secondRunJSONs = new ArrayList<File>();
List<File> thirdRunJSONs = new ArrayList<File>();
List<File> fourthRunJSONs = new ArrayList<File>();
List<File> fifthRunJSONs = new ArrayList<File>();
for (File f : jsons) {
if (f.getName().contains("cucumber1") && f.getName().endsWith(".json")) {
firstRunJSONs.add(f);
} else if (f.getName().contains("cucumber2") && f.getName().endsWith(".json")) {
secondRunJSONs.add(f);
} else if (f.getName().contains("cucumber3") && f.getName().endsWith(".json")) {
thirdRunJSONs.add(f);
} else if (f.getName().contains("cucumber4") && f.getName().endsWith(".json")) {
fourthRunJSONs.add(f);
} else if (f.getName().contains("cucumber5") && f.getName().endsWith(".json")) {
fifthRunJSONs.add(f);
} else {
defaultRunJSONs.add(f);
}
}

if (defaultRunJSONs.size() != 0) {
generateRunWiseReport(defaultRunJSONs, "Default_Run");
}
if (firstRunJSONs.size() != 0) {
generateRunWiseReport(firstRunJSONs, "First_Re-Run");
}
if (secondRunJSONs.size() != 0) {
generateRunWiseReport(secondRunJSONs, "Second_Re-Run");
}
if (thirdRunJSONs.size() != 0) {
generateRunWiseReport(thirdRunJSONs, "Third_Re-Run");
}
if (fourthRunJSONs.size() != 0) {
generateRunWiseReport(fourthRunJSONs, "Fourth_Re-Run");
}
if (fifthRunJSONs.size() != 0) {
generateRunWiseReport(fifthRunJSONs, "Fifth_Re-Run");
}

} catch (Exception e) {
e.printStackTrace();
}
}

public static List<File> finder(String dirName) {
return (List<File>) FileUtils.listFiles(new File(dirName), new String[] {"json"}, true);
}

public static void generateRunWiseReport(List<File> jsons, String run) {
try {
File rd = new File("target/cucumber-parallel/Consolidated-Report/" + run);
List<String> jsonReports = new ArrayList<String>();
for (File json : jsons) {
jsonReports.add(json.getAbsolutePath());
}
//List<String> jsonReports, File reportDirectory, String pluginUrlPath, String buildNumber, String buildProject, boolean skippedFails, boolean undefinedFails, boolean flashCharts, boolean runWithJenkins, boolean artifactsEnabled, String artifactConfig, boolean highCharts
ReportBuilder reportBuilder = new ReportBuilder(jsonReports, rd, "", run, "cucumber-reporting", true, true, true, false, false, "", false);
reportBuilder.generateReports();
System.out.println(run + " consolidated reports are generated under directory target/cucumber-parallel/Consolidated-Report");
} catch (Exception e) {
e.printStackTrace();
}
}
}

"""
Loading