Skip to content

Commit

Permalink
Adopted changes in cucumber 5.0.0 release
Browse files Browse the repository at this point in the history
Cucumber min supported version 5.0.0 and QAF min supported version
3.0.0-beta-2

* Fixed #1 Parameterized background support with cucumber runner
* Fixed #2 Cucumber step with Data table having more than one argument
is not working when we run with TestNG using BDDFactory2
  • Loading branch information
cjayswal committed Feb 10, 2020
1 parent 29940e2 commit dcbec14
Show file tree
Hide file tree
Showing 40 changed files with 1,815 additions and 91 deletions.
7 changes: 5 additions & 2 deletions .classpath
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/qaf/build/artifacts/jars/qaf-sources.jar"/>
<classpathentry kind="lib" path="/qaf/build/artifacts/jars/qaf.jar" sourcepath="/qaf/src"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=qaf-cucumber&amp;ivyXmlPath=ivy.xml&amp;confs=*"/>
<classpathentry kind="src" path="test/src"/>
<classpathentry kind="con" path="org.apache.ivyde.eclipse.cpcontainer.IVYDE_CONTAINER/?project=qaf-cucumber&amp;ivyXmlPath=ivy-test.xml&amp;confs=*&amp;ivySettingsPath=ivysettings.xml&amp;loadSettingsOnDemand=false&amp;ivyUserDir=&amp;propertyFiles="/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/bin/
/build/
/test-results/
88 changes: 81 additions & 7 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@
<format property="build.timestamp" pattern="dd-MMM-yyyy HH:mm:ss" />
</tstamp>

<property name="bin.dir" value="${basedir}/bin" />
<property name="src.dir" value="${basedir}/src" />
<property name="project.dir" value="${basedir}" />

<property name="bin.dir" value="${project.dir}/bin" />
<property name="src.dir" value="${project.dir}/src" />
<property name="test.dir" value="${project.dir}/test" />
<property name="test.src.dir" value="${test.dir}/src" />
<property name="ivy-test.xml" value="${project.dir}/ivy-test.xml" />
<property name="ivy.xml" value="${project.dir}/ivy.xml" />


<property name="meta.dir" value="${basedir}/META-INF" />
<property name="debuglevel" value="source,lines,vars" />
<property name="target" value="1.8" />
Expand All @@ -22,6 +30,13 @@
<include name="**/*.jar" />
</fileset>
</path>
<path id="test.classpath">
<fileset dir="${dist.dir}">
<include name="*.jar" />
<include name="**/*.jar" />
</fileset>
<path refid="build.classpath" />
</path>

<!-- IVY -->
<target name="download-ivy" unless="skip.download">
Expand Down Expand Up @@ -49,16 +64,21 @@

<!-- ================================= target: resolve ================================= -->
<target name="resolve" description="--> retrieve dependencies with ivy" depends="install-ivy">


<ivy:resolve file="ivy.xml" />
<ivy:resolve file="${ivy.xml}" />
<ivy:cachepath pathid="lib.path.id" />

<ivy:addpath topath="build.classpath">
<path refid="lib.path.id" />
</ivy:addpath>
</target>
<target name="resolve-test" description="--> retrieve dependencies with ivy" depends="install-ivy">
<ivy:resolve file="${ivy-test.xml}" />
<ivy:cachepath pathid="lib.path.id" />

<ivy:addpath topath="test.classpath">
<path refid="lib.path.id" />
</ivy:addpath>
</target>
<target name="init" depends="resolve">
<mkdir dir="${bin.dir}" />
<mkdir dir="${dist.dir}" />
Expand All @@ -79,12 +99,22 @@
<target depends="init" name="compile">
<mkdir dir="${bin.dir}" />
<echo level="info">--- compile (start) ---</echo>
<javac debug="false" destdir="${bin.dir}" source="${source}" target="${target}">
<javac debug="true" destdir="${bin.dir}" source="${source}" target="${target}" >
<src path="${src.dir}" />
<classpath refid="build.classpath" />
</javac>
<echo level="info">--- compile (finished) ---</echo>
</target>

<target depends="resolve-test, compile" name="test-compile">
<mkdir dir="${bin.dir}" />
<echo level="info">--- compile (start) ---</echo>
<javac debug="true" destdir="${bin.dir}" source="${source}" target="${target}">
<src path="${test.src.dir}" />
<classpath refid="test.classpath" />
</javac>
<echo level="info">--- compile (finished) ---</echo>
</target>
<!-- ================================= target: build ================================= -->
<target name="build" depends="make-jar, gendoc, gensource" description="build framework, generate docs">

Expand Down Expand Up @@ -114,6 +144,9 @@
<service type="io.cucumber.core.backend.BackendProviderService">
<provider classname="com.qmetry.qaf.automation.cucumber.QAFBackendProviderService" />
</service>
<service type="io.cucumber.core.gherkin.FeatureParser">
<provider classname="com.qmetry.qaf.automation.cucumber.bdd2.parser.BDD2FeatureParser" />
</service>
</jar>
</target>

Expand Down Expand Up @@ -143,7 +176,48 @@
</manifest>
</jar>
</target>
<target name="publish" depends="init, build">
<target name="junit-test" depends="resolve-test">
<mkdir dir="${test.dir}/test-results/junit" />
<echo>${bin.dir} \n ${basedir}</echo>
<junit printsummary="yes" haltonfailure="true" fork="true" dir="${test.dir}">
<!-- Project classpath, must include junit.jar -->
<classpath refid="test.classpath" />
<!-- test class -->
<classpath location="${bin.dir}" />

<test fork="false" name="com.qmetry.qaf.automation.cucumber.test.RunCucumberTest" haltonfailure="no" todir="${test.dir}/test-results/junit">
<formatter type="plain" />
<formatter type="xml" />
</test>

</junit>
</target>

<target name="test" depends="build, test-compile" description="run tests">
<delete dir="${test.dir}/test-results" failonerror="false" />
<!-- --><antcall target="junit-test" >
<param name="basedir" value="${test.dir}" />
<param name="project.dir" value="../" />
</antcall>
<taskdef resource="testngtasks" classpathref="test.classpath" />
<testng classpathref="test.classpath" workingDir="${test.dir}" outputDir="${test.dir}/test-results" haltOnFailure="no" verbose="2">
<classpath location="${bin.dir}" />
<xmlfileset dir="${test.dir}/config" includes="testrun_config.xml" />
<sysproperty key="log4j.configuration" value="file:///${test.dir}/log4j.properties" />
</testng>
<!--<testng classpathref="test.classpath" workingDir="${test.dir}" outputDir="${test.dir}/test-results" haltOnFailure="no" verbose="2">
<classpath location="${bin.dir}" />
<classfileset dir="${bin.dir}" includes="**/*.class" />
<sysproperty key="log4j.configuration" value="file:///${test.dir}/log4j.properties" />
</testng> -->

<!-- run cucumener using junit runner -->



</target>
<target name="publish" depends="init, build, test">
<!-- Determine build number from previously published revisions -->
<ivy:buildnumber resolver="${publish.resolver}" organisation="${ivy.organisation}" module="${ivy.module}" revision="${release.num}" />

Expand Down
42 changes: 42 additions & 0 deletions ivy-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for additional
information regarding copyright ownership. The ASF licenses this file to
you under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of
the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License. -->
<ivy-module version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
<info organisation="com.qmetry" module="qaf-cucumber" status="integration">
</info>
<configurations>
<conf name="compile" description="Required to compile application"/>
<conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
<conf name="test" description="Required for test only" extends="runtime"/>
<conf name="provided" description="Needed for compile, but will be present on the target platform."/>
</configurations>

<dependencies>
<dependency org="com.qmetry" name="qaf" rev="3.0.0-beta-1" conf="compile->default"/>
<dependency org="io.cucumber" name="cucumber-core" rev="5.0.0" conf="compile->default"/>
<dependency org="io.cucumber" name="gherkin" rev="5.2.0" conf="compile->default"/>

<dependency org="io.cucumber" name="gherkin-jvm-deps" rev="1.0.6" conf="compile->default"/>


<dependency org="io.cucumber" name="cucumber-java8" rev="5.0.0" conf="test->default"/>
<dependency org="io.cucumber" name="cucumber-java" rev="5.0.0" conf="test->default"/>
<dependency org="io.cucumber" name="cucumber-junit" rev="5.0.0" conf="test->default"/>
<dependency org="io.cucumber" name="cucumber-spring" rev="5.0.0" conf="test->default"/>
<dependency org="org.springframework" name="spring-core" rev="5.2.0.RELEASE" conf="test->default"/>
<dependency org="org.springframework" name="spring-beans" rev="5.2.0.RELEASE" conf="test->default"/>
<dependency org="org.springframework" name="spring-context" rev="5.2.0.RELEASE" conf="test->default"/>
<dependency org="org.springframework" name="spring-test" rev="5.2.0.RELEASE" conf="test->default"/>

</dependencies>
</ivy-module>
6 changes: 4 additions & 2 deletions ivy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
</configurations>

<dependencies>
<dependency org="com.qmetry" name="qaf" rev="3.0.0-beta-1" conf="compile->default"/>
<dependency org="io.cucumber" name="cucumber-core" rev="5.0.0-RC1" conf="provided->default"/>
<dependency org="com.qmetry" name="qaf" rev="3.0.0-beta-2" conf="compile->default"/>
<dependency org="io.cucumber" name="cucumber-core" rev="5.0.0" conf="provided->default"/>
<dependency org="io.cucumber" name="gherkin" rev="5.2.0" conf="compile->default"/>
<dependency org="io.cucumber" name="gherkin-jvm-deps" rev="1.0.6" conf="compile->default"/>
</dependencies>
</ivy-module>
27 changes: 0 additions & 27 deletions src/com/qmetry/qaf/automation/cucumber/Bdd2PickleStep.java

This file was deleted.

16 changes: 12 additions & 4 deletions src/com/qmetry/qaf/automation/cucumber/CucumberStep.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.qmetry.qaf.automation.step.QAFTestStepArgumentFormatter;
import com.qmetry.qaf.automation.step.QAFTestStepArgumentFormatterImpl;
import com.qmetry.qaf.automation.step.TestStep;
import com.qmetry.qaf.automation.util.ClassUtil;

import io.cucumber.core.backend.CucumberInvocationTargetException;
import io.cucumber.core.backend.ParameterInfo;
Expand All @@ -42,14 +43,21 @@ public class CucumberStep extends BaseTestStep {
public CucumberStep(StepDefinition s) {
super(s.toString(), getPattern(s));
this.s = s;

setStepMatcher(new CucumberStepMatcher());
}

private static String getPattern(StepDefinition s) {
String pattern = s.getPattern();
if (s.parameterInfos().isEmpty() || pattern.contains("{")) {
return pattern;
List<ParameterInfo> params = s.parameterInfos();
if (null != params && !params.isEmpty()) {
Type last = params.get(params.size() - 1).getType();
if (ClassUtil.isAssignableFrom(last, DataTable.class)) {
pattern = pattern + "{string}";
}
}
return pattern + "{0}";
// pattern = processEscapes(pattern);
return pattern;
}

@Override
Expand Down Expand Up @@ -116,6 +124,7 @@ protected Object[] processArgs(List<ParameterInfo> list, Object... objects) {
Type paramType = list.get(i).getType();
context.put("__paramType", paramType);
context.put("__paramIndex", i);

if (paramType.getTypeName().endsWith("DataTable")) {
formatter = new DataTableFormattor();
}
Expand Down Expand Up @@ -225,5 +234,4 @@ private Object getObject(String key, Class<?> paramType) {
}

}

}
87 changes: 87 additions & 0 deletions src/com/qmetry/qaf/automation/cucumber/CucumberStepMatcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
*
*/
package com.qmetry.qaf.automation.cucumber;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.qmetry.qaf.automation.step.BDDStepMatcherFactory.DefaultBDDStepMatcher;

import io.cucumber.core.exception.CucumberException;

/**
* @author chirag.jayswal
*
*/
public class CucumberStepMatcher extends DefaultBDDStepMatcher {
private static final Pattern PARAMETER_PATTERN = Pattern.compile("(\\\\\\\\)?\\{([^}]*)\\}");
private static final Pattern OPTIONAL_PATTERN = Pattern.compile("(\\\\\\\\)?\\(([^)]+)\\)");
private static final Pattern ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP = Pattern.compile("([^\\s^/]+)((/[^\\s^/]+)+)");
private static final String DOUBLE_ESCAPE = "\\\\";
private static final String PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE = "Parameter types cannot be alternative: ";
private static final String PARAMETER_TYPES_CANNOT_BE_OPTIONAL = "Parameter types cannot be optional: ";

@Override
public boolean matches(String stepDescription, String stepCall, Map<String, Object> context) {
stepDescription = processOptional(stepDescription);
stepDescription = processAlternation(stepDescription);
return super.matches(stepDescription, stepCall, context);
}

@Override
public List<String[]> getArgsFromCall(String stepDescription, String stepCall, Map<String, Object> context) {
stepDescription = processOptional(stepDescription);
stepDescription = processAlternation(stepDescription);
return super.getArgsFromCall(stepDescription, stepCall, context);
}

private static String processOptional(String expression) {
Matcher matcher = OPTIONAL_PATTERN.matcher(expression);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// look for double-escaped parentheses
String parameterPart = matcher.group(2);
if (DOUBLE_ESCAPE.equals(matcher.group(1))) {
matcher.appendReplacement(sb, "\\\\(" + parameterPart + "\\\\)");
} else {
checkNotParameterType(parameterPart, PARAMETER_TYPES_CANNOT_BE_OPTIONAL);
matcher.appendReplacement(sb, "(?:" + parameterPart + ")?");
}
}
matcher.appendTail(sb);
return sb.toString();
}

private static String processAlternation(String expression) {
Matcher matcher = ALTERNATIVE_NON_WHITESPACE_TEXT_REGEXP.matcher(expression);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// replace \/ with /
// replace / with |
String replacement = matcher.group(0).replace('/', '|').replaceAll("\\\\\\|", "/");

if (replacement.contains("|")) {
// Make sure the alternative parts don't contain parameter types
for (String part : replacement.split("\\|")) {
checkNotParameterType(part, PARAMETER_TYPES_CANNOT_BE_ALTERNATIVE);
}
matcher.appendReplacement(sb, "(?:" + replacement + ")");
} else {
// All / were escaped
matcher.appendReplacement(sb, replacement);
}
}
matcher.appendTail(sb);
return sb.toString();
}

private static void checkNotParameterType(String s, String message) {
Matcher matcher = PARAMETER_PATTERN.matcher(s);
if (matcher.find()) {
throw new CucumberException(message + s);
}
}
}
Loading

0 comments on commit dcbec14

Please sign in to comment.