Skip to content

Commit

Permalink
new setup hook working with build passing #1905
Browse files Browse the repository at this point in the history
remaining - include the extra scenario in reports
documentation, and the support for multiple named setup scenarios in a feature
  • Loading branch information
ptrthomas committed Aug 7, 2022
1 parent 8805f3d commit 26907ec
Show file tree
Hide file tree
Showing 27 changed files with 131 additions and 155 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ public Object setup() {
Feature feature = engine.runtime.featureRuntime.feature;
Scenario scenario = feature.getSetup();
ScenarioRuntime sr = new ScenarioRuntime(engine.runtime.featureRuntime, scenario);
sr.setSkipBackground(true);
sr.run();
return JsValue.fromJava(sr.engine.getAllVariablesAsMap());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.slf4j.Logger;

/**
*
Expand Down Expand Up @@ -88,6 +89,7 @@ public boolean tryAdvance(Consumer<? super ScenarioRuntime> action) {
}
}
if (currentScenario.isDynamic()) {
Logger logger = FeatureRuntime.logger;
if (expressionValue == null) {
String expression = currentScenario.getDynamicExpression();
dynamicRuntime = new ScenarioRuntime(featureRuntime, currentScenario);
Expand All @@ -103,6 +105,7 @@ public boolean tryAdvance(Consumer<? super ScenarioRuntime> action) {
}
} catch (Exception e) {
String message = "dynamic expression evaluation failed: " + expression;
logger.error("{} - {}", currentScenario, message);
dynamicRuntime.result.addFakeStepResult(message, e);
currentScenario = null;
action.accept(dynamicRuntime);
Expand All @@ -120,6 +123,7 @@ public boolean tryAdvance(Consumer<? super ScenarioRuntime> action) {
rowValue = dynamicRuntime.engine.executeFunction(expressionValue, rowIndex);
} catch (Exception e) {
String message = "dynamic function expression evaluation failed at index " + rowIndex + ": " + e.getMessage();
logger.error("{} - {}", currentScenario, message);
dynamicRuntime.result.addFakeStepResult(message, e);
currentScenario = null;
action.accept(dynamicRuntime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public class ScenarioRuntime implements Runnable {
public final boolean dryRun;
public final LogAppender logAppender;

public boolean ignoringFailureSteps;
private boolean skipBackground;
private boolean ignoringFailureSteps;

public ScenarioRuntime(FeatureRuntime featureRuntime, Scenario scenario) {
logger = new Logger();
Expand Down Expand Up @@ -127,10 +128,6 @@ public boolean isFailed() {
return error != null || result.isFailed();
}

public boolean isIgnoringFailureSteps() {
return ignoringFailureSteps;
}

public Step getCurrentStep() {
return currentStep;
}
Expand All @@ -139,6 +136,10 @@ public boolean isStopped() {
return stopped;
}

public void setSkipBackground(boolean skipBackground) {
this.skipBackground = skipBackground;
}

public String getEmbedFileName(ResourceType resourceType) {
String extension = resourceType == null ? null : resourceType.getExtension();
return scenario.getUniqueId() + "_" + System.currentTimeMillis() + (extension == null ? "" : "." + extension);
Expand Down Expand Up @@ -338,8 +339,8 @@ private static boolean isSelectedForExecution(FeatureRuntime fr, Scenario scenar

//==========================================================================
//
public void beforeRun() {
steps = scenario.getStepsIncludingBackground();
public void beforeRun() {
steps = skipBackground ? scenario.getSteps() : scenario.getStepsIncludingBackground();
ScenarioEngine.set(engine);
engine.init();
result.setExecutorName(Thread.currentThread().getName());
Expand Down Expand Up @@ -449,7 +450,7 @@ public StepResult execute(Step step) {
if (currentStepResult.isErrorIgnored()) {
engine.setFailedReason(null);
}
if (!engine.isIgnoringStepErrors() && isIgnoringFailureSteps()) {
if (!engine.isIgnoringStepErrors() && ignoringFailureSteps) {
if (engine.getConfig().isContinueAfterContinueOnStepFailure()) {
// continue execution and reset failed reason for engine to null
engine.setFailedReason(null);
Expand Down
1 change: 1 addition & 0 deletions karate-core/src/main/java/com/intuit/karate/core/Tag.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class Tag {
public static final String IGNORE = "ignore";
public static final String ENV = "env";
public static final String ENVNOT = "envnot";
public static final String SETUP = "setup";

private final int line;
private final String text;
Expand Down
3 changes: 3 additions & 0 deletions karate-core/src/main/java/com/intuit/karate/core/Tags.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ public boolean evaluate(String tagSelector, String karateEnv) {
if (StringUtils.containsIgnoreCase(tags, Tag.IGNORE)) {
return false;
}
if (tagValues.containsKey(Tag.SETUP)) {
return false;
}
Values envValues = valuesFor(Tag.ENV);
if (envValues.isPresent) {
if (karateEnv == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
Feature:

Background:
* def anotherVariable = 'hello'
@setup
Scenario:
* def data = [{ name: 'one' }, { name: 'two' }]

Scenario Outline:
* match name == "#present"
* match anotherVariable == "hello"

Examples:
| data |
| karate.setup().data |

Scenario Outline:
* match name == "#present"
* match anotherVariable == "hello"

Examples:
| name |
| test |

Scenario Outline:
* match name == "#present"
* match anotherVariable == "hello"
* def params = { 'foo': 'bar' }
* call read('js-read-called-2.feature') params

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,44 +1,12 @@
Feature:

Background:
* def anotherVariable = 'hello'
@setup
Scenario:
* def x = read('js-read-3.json')
* def data = x.thirderror
* def backgroundVar =
"""
{"foo": '#(data)' }
"""

Scenario Outline:
* match backgroundVar == { "foo": "#(data)" }
* match id == "#present"
* match anotherVariable == "hello"
* match id == '#number'

Examples:
| data |

Scenario Outline:
* def param =
"""
{ bar: '#(backgroundVar)'}
"""
* match param == { bar: '#(backgroundVar)'}
* match id == "#present"
* match anotherVariable == "hello"

Examples:
| data |


Scenario Outline:
* def params =
"""
{ backgroundVar: '#(backgroundVar)'}
"""
* print params
* match id == "#present"
* match anotherVariable == "hello"
* call read('js-read-called-2.feature') params

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
Feature:

Background:
#* call read('js-read-3.json')
* call read('../utils-reuse-common.feature')

Scenario:
* print 'arg: ' + __arg
* match __arg == "#present"
* match __arg == "#notnull"
* match __arg == { foo: 'bar' }
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
Feature:

Background:
* def foo = 'hello'
* def fun = function(){ return 'bar' }
* configure driver = { type: "noopdriver" }
* driver 'http://google.com'
* table data
| name | extra |
| 'one' | |
| 'two' | configSource |
@setup
Scenario:
* table data
| name | extra |
| 'one' | |
| 'two' | configSource |

Scenario Outline:
* assert name == 'one' || name == 'two'
* assert name == 'two' ? extra == 'normal' : true
* match foo == "hello"
* match fun() == 'bar'
* click("#testing.usage.driver.method")
* assert name == 'one' || name == 'two'
* assert name == 'two' ? extra == 'normal' : true

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
Feature: function from global config
Feature:

Background:
* def data = [ { name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' } ]
@setup
Scenario:
* def data = [{ name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' }]

Scenario Outline:
* print 'name:', name

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
Feature:

@ignore @setup
Background:
* print 'in background', __num

@setup
Scenario:
* print 'in setup'
* def data = [{a:1}, {a:2}]

Scenario Outline:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
Feature:

Background:
@setup
Scenario:
* def generator = function(i){ if (i == 5) return null; return { name: 'cat' + i, age: i } }

Scenario Outline:
* match __num == age
* match __row.name == 'cat' + age

Examples:
| generator |
| karate.setup().generator |
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
Feature:

Background:
* def isNot = function(x) { return function(row) { return row.id != x } }
* callonce read('call-once-from-feature.feature')
@setup
Scenario:
* def data = read('data.csv')
* def exclude = x => data.filter(y => y.id != x)
* def include = x => data.filter(y => y.id == x)

Scenario Outline:
* call read('called.feature')
* assert id != '0'

Examples:
| karate.filter(read('data.csv'), isNot('0')) |
| karate.setup().data.filter(x => x.id != '0') |

Scenario Outline:
* call read('called.feature')
* assert id != '1'

Examples:
| karate.filter(read('data.csv'), isNot('1')) |
| karate.setup().exclude('1') |

Scenario Outline:
* call read('called.feature')
* assert id != '2'
* assert id == '2'

Examples:
| karate.filter(read('data.csv'), isNot('2')) |
| karate.setup().include('2') |
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
@trigger-by-tag
Feature:

Background:
# background http builder should work even for a dynamic scenario outline
* url serverUrl
* def data = [ { name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' } ]
* url serverUrl
# java object that comes from a callSingle in the config
* def HelloBg = HelloConfigSingle
* callonce read('call-once-from-feature.feature')
Expand All @@ -23,6 +21,10 @@ Background:
}
"""

@setup
Scenario:
* def data = [ { name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' } ]

Scenario Outline:
* call read('called.feature')
* match functionFromKarateBase() == 'fromKarateBase'
Expand All @@ -31,13 +33,12 @@ Scenario Outline:
* status 200
* match response == { message: 'from feature' }


* match HelloBg.sayHello('world') == 'hello world'
* match HelloOnce.sayHello('world') == 'hello world'
* match sayHello('world') == 'hello world'

Examples:
| data |
| karate.setup().data |

Scenario Outline: validating background http context set in background will be shared in shared scope, with dynamic scenario outline
* call read('called.feature')
Expand All @@ -51,4 +52,4 @@ Scenario Outline: validating background http context set in background will be s
* match sayHello('world') == 'hello world'

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
Feature:

Background:
* def data = [ { name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' } ]
@setup
Scenario:
* def data = [{ name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' }]

Scenario Outline:
* match functionFromKarateBase() == 'fromKarateBase'

Examples:
| data |
| karate.setup().data |
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
Feature:

Background:
* def data = [{ name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' }]
* call read('headers.feature')
* call read('headers.feature')

@setup
Scenario:
* def data = [{ name: 'value1' }, { name: 'value2' }, { name: 'value3' }, { name: 'value4' }]

Scenario Outline:
* url 'http://localhost:' + karate.properties['server.port']
Expand All @@ -12,5 +15,5 @@ Scenario Outline:
* match response == { message: 'from feature' }

Examples:
| data |
| karate.setup().data |

Loading

0 comments on commit 26907ec

Please sign in to comment.