Skip to content

Commit

Permalink
Merge pull request #63 from vpTechOSS/feature/fix-reports
Browse files Browse the repository at this point in the history
Feature/fix reports
  • Loading branch information
josefd8 authored Dec 29, 2020
2 parents d0c7b7c + bcaca5b commit ba6f251
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 52 deletions.
34 changes: 33 additions & 1 deletion src/main/java/com/privalia/qa/aspects/LoopIncludeTagAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.privalia.qa.exceptions.IncludeException;
//import cucumber.runtime.io.Resource;
import com.privalia.qa.exceptions.NonReplaceableException;
import io.cucumber.core.feature.FeatureParser;
import io.cucumber.core.resource.Resource;
import io.cucumber.testng.FeatureWrapper;
Expand All @@ -33,6 +34,8 @@
import java.util.ArrayList;
import java.util.List;

import static com.privalia.qa.aspects.ReplacementAspect.replaceEnvironmentPlaceholders;

/**
* Aspect for managing the @include, @background and @loop tags. This particulars tags must be handled right
* after the feature file is read
Expand Down Expand Up @@ -77,7 +80,6 @@ public String aroundAddLoopTagPointcutScenario(ProceedingJoinPoint pjp, Resource
int endIndex = path.lastIndexOf("/") + 1;
path = path.substring(0, endIndex);


for (int s = 0; s < lines.size(); s++) {
String[] elems;
if (lines.get(s).toUpperCase().matches("\\s*@LOOP.*")) {
Expand Down Expand Up @@ -125,10 +127,40 @@ public String aroundAddLoopTagPointcutScenario(ProceedingJoinPoint pjp, Resource
}
}
parseLines(lines, path);

/* Perform any possible replacement to the file from the start */
this.initialReplacements(lines);

return String.join("\n", lines);

}

/**
* Starts by doing variable replacement on each line of the feature file
* as soon as it finds a line that starts with the keyword "Scenario", "Scenario Outline:"
* "Background:" or "Rule", it switches to changing only the lines with that keyword.
* This is to not do variable replacements on the steps.
*
* The reason for this is because the steps may contain variables that do not yet
* exists (ThreadProperty variables), and this could bring unexpected replacements
* like ${toUpperCase:${myvar}} -> ${MYVAR}
*/
private List<String> initialReplacements(List<String> lines) throws NonReplaceableException {
boolean stop = false;
for (int s = 0; s < lines.size(); s++) {
String debug = lines.get(s);
if (lines.get(s).matches("\\s*Scenario:.*") || lines.get(s).matches("\\s*Scenario Outline:.*") || lines.get(s).matches("\\s*Background:.*") || lines.get(s).matches("\\s*Rule:.*")) {
lines.set(s, replaceEnvironmentPlaceholders(lines.get(s), null));
stop = true;
}

if (!stop) {
lines.set(s, replaceEnvironmentPlaceholders(lines.get(s), null));
}
}
return lines;
}


public void exampleLines (String name, String[] params, List<String> lines, int num) {
lines.add(num, "| " + name + " | " + name + ".id |");
Expand Down
25 changes: 4 additions & 21 deletions src/main/java/com/privalia/qa/aspects/ReplacementAspect.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.privalia.qa.specs.CommonG;
import com.privalia.qa.utils.ThreadProperty;
import io.cucumber.core.backend.TestCaseState;
import io.cucumber.core.resource.Resource;
import io.cucumber.core.stepexpression.DataTableArgument;
import io.cucumber.core.stepexpression.DocStringArgument;
import io.cucumber.core.stepexpression.ExpressionArgument;
Expand All @@ -40,6 +41,7 @@
import org.apache.commons.text.lookup.StringLookup;
import org.apache.commons.text.lookup.StringLookupFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
Expand All @@ -48,11 +50,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.*;

Expand All @@ -77,25 +79,6 @@ public final class ReplacementAspect {
private static StringSubstitutor interpolator = new StringSubstitutor(StringLookupFactory.INSTANCE.interpolatorStringLookup(stringLookupMap, new DefaultLookUp(), true))
.setEnableSubstitutionInVariables(true);

private Object lastEchoedStep;

@Pointcut("execution (String io.cucumber.core.gherkin.messages.GherkinMessagesPickle.getName(..)) && args()")
protected void replacementScenarios() {
}

@Around(value = "replacementScenarios()")
public String aroundReplacementScenarios(JoinPoint jp) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, FileNotFoundException, NonReplaceableException, ConfigurationException, URISyntaxException {

Object GherkinMessage = jp.getThis();
Field pickleField = GherkinMessage.getClass().getDeclaredField("pickle");
pickleField.setAccessible(true);
Object pickle = pickleField.get(GherkinMessage);
Method m = pickle.getClass().getDeclaredMethod("getName", null);
m.setAccessible(true);
String scenarioName = (String) m.invoke(pickle, null);
return replacedElement(scenarioName, jp);

}

@Pointcut("execution (* io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(..)) && args(state)")
protected void replacementArguments(TestCaseState state) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
package com.privalia.qa.cucumber.reporter;

import com.privalia.qa.aspects.ReplacementAspect;
import com.privalia.qa.exceptions.NonReplaceableException;
import com.privalia.qa.utils.ThreadProperty;
import io.cucumber.core.exception.CucumberException;
import io.cucumber.core.stepexpression.ExpressionArgument;
import io.cucumber.messages.Messages;
import io.cucumber.plugin.ColorAware;
import io.cucumber.plugin.ConcurrentEventListener;
import io.cucumber.plugin.event.*;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -202,9 +199,9 @@ private void printFeature(String path) {
Format format = formats.get("pending_arg");
out.println(tagsList);

out.println(feature.getKeyword() + ": " + this.getReplacedValue(feature.getName()));
out.println(feature.getKeyword() + ": " + feature.getName());
if (feature.getDescription() != null) {
out.println(this.getReplacedValue(feature.getDescription()));
out.println(feature.getDescription());
}
}

Expand Down
73 changes: 73 additions & 0 deletions src/main/java/com/privalia/qa/specs/UtilsGSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.*;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -469,4 +470,76 @@ public void resultsMustBe(DataTable expectedResults) throws Exception {
commonspec.getLogger().warn("default switch branch on results check");
}
}

/**
* Creates a random integer within range
* <p>
* Creates a random number within the range provided and saves it in a variable
* for later use
* <br>
* <pre>
* Example:
* {@code
* Given I create a random number between '0' and '10' and save it in the variable 'RANDOM'
* And I wait '${RANDOM}' seconds
* }
* </pre>
*
* @see #generateRandomStrings(String, Integer, String)
* @param lowerLimit lower limit in range
* @param upperLimit upper limit in range
* @param varName name of the variable to save the result
*/
@Given("^I generate a random number between '(.*)' and '(.*)' and save it in the variable '(.*)'$")
public void generateRandomNumberInRange(Integer lowerLimit, Integer upperLimit, String varName) {
Assertions.assertThat(lowerLimit).as("").isLessThan(upperLimit);
Random random = new Random();
Integer rndint = random.nextInt(upperLimit - lowerLimit) + lowerLimit;
ThreadProperty.set(varName, rndint.toString());
}

/**
* Generate numeric or alphanumeric strings
* <p>
* Generates a string that can be numeric ([0-9]) or alphanumeric ([0-9][A-Z][a-z]) of a given length
* and saves it in a variable for furute use
* <br>
* <pre>
* Example: Generating a random numeric string of length 20
* {@code
* Given I generate a random 'numeric' string of length '20' and save it in the variable 'NUMERIC'
* }
* Example: Generating a random alphanumeric string of length 20
* {@code
* Given I generate a random 'alphanumeric' string of length '20' and save it in the variable 'ALPHANUMERIC'
* }
* </pre>
*
* @see #generateRandomNumberInRange(Integer, Integer, String)
* @param type string type: numeric|alphanumeric
* @param length string final length
* @param varName name of the variable to save the result
*/
@Given("^I generate a random '(numeric|alphanumeric)' string of length '(.*)' and save it in the variable '(.*)'$")
public void generateRandomStrings(String type, Integer length, String varName) {

Assertions.assertThat(length).as("Length must be greater than zero!").isGreaterThan(0);
SecureRandom random = new SecureRandom();
String out = "";

if (type.matches("numeric")) {
for (int i = 0; i <= length - 1; i++) {
Integer rndint = random.nextInt(9 - 0) + 0;
out = out.concat(rndint.toString());
}
} else {
String AB = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append(AB.charAt(random.nextInt(AB.length())));
}
out = sb.toString();
}
ThreadProperty.set(varName, out);
}
}
11 changes: 10 additions & 1 deletion src/test/resources/features/replacementAspect.feature
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,13 @@ Feature: Testing variable replacements ${VERSION}
Examples:
| content | file |
| {"a":{},"1":{},"b":"1"} | empty |
| {"a":{},"1":{},"b":"1"} | simple0 |
| {"a":{},"1":{},"b":"1"} | simple0 |

Scenario: Create random numbers
Given I generate a random 'numeric' string of length '20' and save it in the variable 'NUMERIC'
#log ${NUMERIC}
Given I generate a random 'alphanumeric' string of length '20' and save it in the variable 'ALPHANUMERIC'
#log ${ALPHANUMERIC}
Given I generate a random number between '0' and '10' and save it in the variable 'RANDOM'
#log ${RANDOM}
And I wait '1' seconds
28 changes: 14 additions & 14 deletions src/test/resources/features/selenium.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ Feature: Selenium steps
steps for testing web pages using selenium (such as this one) must include the "@web" annotation at the beginning of the file.
This is necessary, since it signals the library that it should bootstrap selenium and other important components.

Scenario: Testing direct steps and new locators
Given I go to 'http://${DEMO_SITE_HOST}/index.html@p=49.html'
When I type 'Jose' on the element with 'id:name_3_firstname'
Then I type 'Fernandez' on the element with 'id:name_3_lastname' index '0'
Then I click on the element with 'name:radio_4[]' index '0'
Then I click on the element with 'name:checkbox_5[]' index '1'
Then I click on the element with 'name:checkbox_5[]' index '2'
Then I scroll down until the element with 'name:pie_submit' is visible
Then I scroll up until the element with 'id:name_3_firstname' is visible
Then I scroll down until the element with 'name:pie_submit' is visible
Then I click on the element with 'name:pie_submit'
Then I wait '3' seconds


Scenario: Finding a text anywhere on the page
Given My app is running in '${DEMO_SITE_HOST}'
When I browse to '/'
Expand Down Expand Up @@ -161,17 +175,3 @@ Feature: Selenium steps
And I wait '3' seconds
And I execute 'return document.URL;' as javascript and save the result in the environment variable 'PAGE'
And '!{PAGE}' contains 'index.html'


Scenario: Testing direct steps and new locators
Given I go to 'http://${DEMO_SITE_HOST}/index.html@p=49.html'
When I type 'Jose' on the element with 'id:name_3_firstname'
Then I type 'Fernandez' on the element with 'id:name_3_lastname' index '0'
Then I click on the element with 'name:radio_4[]' index '0'
Then I click on the element with 'name:checkbox_5[]' index '1'
Then I click on the element with 'name:checkbox_5[]' index '2'
Then I scroll down until the element with 'name:pie_submit' is visible
Then I scroll up until the element with 'id:name_3_firstname' is visible
Then I scroll down until the element with 'name:pie_submit' is visible
Then I click on the element with 'name:pie_submit'
Then I wait '3' seconds
21 changes: 11 additions & 10 deletions src/test/resources/helpMessage.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@

┌──────────────────────────────────────────────────────────────────────────┐
│ GingerSpec documentation: │
│ https://github.com/vpTechOSS/gingerspec/wiki │
│ |
| Command line options: │
│ -DSHOW_ERRORS_STACKTRACE: Show errors full stacktrace |
| -DlogLevel=DEBUG: Change logging level |
| -DSHOW_STACK_INFO: Shows step definition location and arguments |
| -Dmaven.failsafe.debug: Debug (Intellij IDEA) |
└──────────────────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────────────────────────┐
│ GingerSpec wiki: https://github.com/vpTechOSS/gingerspec/wiki │
│ Discussion/ideas: https://github.com/vpTechOSS/gingerspec/discussions │
│ Report a bug: https://github.com/vpTechOSS/gingerspec/issues |
| |
| Command line options: │
│ -DSHOW_ERRORS_STACKTRACE: Show errors full stacktrace |
| -DlogLevel=DEBUG: Change logging level |
| -DSHOW_STACK_INFO: Shows step definition location and arguments |
| -Dmaven.failsafe.debug: Debug (Intellij IDEA) |
└───────────────────────────────────────────────────────────────────────────────────┘

0 comments on commit ba6f251

Please sign in to comment.