Skip to content

Commit bf3ffb6

Browse files
authored
Merge pull request #667 from luke-zhou/master
ISSUE-659 # add ability to refer CSV source value by header
2 parents b41ea94 + 706f3ad commit bf3ffb6

File tree

11 files changed

+182
-22
lines changed

11 files changed

+182
-22
lines changed

core/src/main/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImpl.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
import org.apache.commons.collections4.CollectionUtils;
88
import org.apache.commons.text.StringSubstitutor;
99
import org.jsmart.zerocode.core.domain.ScenarioSpec;
10+
import org.jsmart.zerocode.core.utils.TokenUtils;
1011
import org.slf4j.Logger;
1112

1213
import java.util.Arrays;
1314
import java.util.HashMap;
1415
import java.util.List;
1516
import java.util.Map;
16-
import java.util.concurrent.atomic.AtomicLong;
17+
import java.util.stream.IntStream;
1718

1819
import static org.jsmart.zerocode.core.constants.ZerocodeConstants.DSL_FORMAT;
1920
import static org.jsmart.zerocode.core.di.provider.CsvParserProvider.LINE_SEPARATOR;
@@ -115,10 +116,13 @@ private ScenarioSpec resolveParamsCsv(ScenarioSpec scenario, int paramIndex) {
115116
return scenario;
116117
}
117118

118-
Map<String, Object> valuesMap = new HashMap<>();
119+
String[] headers = retrieveCsvHeaders(parameterizedCsvList.get(0));
120+
121+
paramIndex = headers == null ? paramIndex : paramIndex+1;
122+
119123
String csvLine = parameterizedCsvList.get(paramIndex);
120124

121-
resolveCsvLine(valuesMap, csvLine);
125+
Map<String, Object> valuesMap = resolveCsvLine(csvLine, headers);
122126

123127
String resultantStepJson = replaceWithValues(stepJson, valuesMap);
124128

@@ -129,11 +133,25 @@ private ScenarioSpec resolveParamsCsv(ScenarioSpec scenario, int paramIndex) {
129133
}
130134
}
131135

132-
private void resolveCsvLine(Map<String, Object> valuesMap, String csvLine) {
136+
private String[] retrieveCsvHeaders(String csvHeaderLine) {
137+
String[] parsedHeaderLine = csvParser.parseLine(csvHeaderLine + LINE_SEPARATOR);
138+
boolean hasHeader = parsedHeaderLine.length > 0 && Arrays.stream(parsedHeaderLine).allMatch(s -> s.matches("^\\|.*\\|$"));
139+
return !hasHeader ? null : Arrays.stream(parsedHeaderLine).map(s -> s.substring(1,s.length()-1)).toArray(String[]::new);
140+
}
141+
142+
private Map<String, Object> resolveCsvLine(String csvLine, String[] headers) {
143+
Map<String, Object> valuesMap = new HashMap<>();
133144
String[] parsedLine = csvParser.parseLine(csvLine + LINE_SEPARATOR);
134-
AtomicLong index = new AtomicLong(0);
135-
Arrays.stream(parsedLine)
136-
.forEach(thisValue -> valuesMap.put(index.getAndIncrement() + "", thisValue));
145+
IntStream.range(0, parsedLine.length).forEach(i -> valuesMap.put(i + "", parsedLine[i]));
146+
147+
if (headers != null){
148+
IntStream.range(0, headers.length).forEach(i -> {
149+
if(!headers[i].contains(" ") && !headers[i].isEmpty()){
150+
valuesMap.put("PARAM."+headers[i], TokenUtils.resolveKnownTokens(parsedLine[i]).toString());
151+
}
152+
});
153+
}
154+
return valuesMap;
137155
}
138156

139157
private String replaceWithValues(String stepJson, Map<String, Object> valuesMap) {

core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@
1010
import static java.util.Optional.ofNullable;
1111
import static org.apache.commons.collections4.CollectionUtils.isEmpty;
1212
import static org.jsmart.zerocode.core.constants.ZerocodeConstants.KAFKA_TOPIC;
13+
14+
import org.jsmart.zerocode.core.domain.Parameterized;
1315
import org.jsmart.zerocode.core.domain.ScenarioSpec;
1416
import org.jsmart.zerocode.core.domain.Step;
1517
import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecReportBuilder;
18+
19+
import static org.jsmart.zerocode.core.di.provider.CsvParserProvider.LINE_SEPARATOR;
1620
import static org.jsmart.zerocode.core.domain.builders.ZeroCodeExecReportBuilder.newInstance;
1721
import org.jsmart.zerocode.core.domain.builders.ZeroCodeIoWriteBuilder;
1822
import org.jsmart.zerocode.core.engine.assertion.FieldAssertionMatcher;
@@ -30,7 +34,6 @@
3034
import org.jsmart.zerocode.core.utils.ApiTypeUtils;
3135
import static org.jsmart.zerocode.core.utils.ApiTypeUtils.apiType;
3236
import static org.jsmart.zerocode.core.utils.RunnerUtils.getFullyQualifiedUrl;
33-
import static org.jsmart.zerocode.core.utils.RunnerUtils.getParameterSize;
3437
import static org.jsmart.zerocode.core.utils.SmartUtils.prettyPrintJson;
3538
import org.junit.runner.Description;
3639
import org.junit.runner.notification.RunNotifier;
@@ -42,6 +45,7 @@
4245
import java.util.List;
4346
import java.util.Objects;
4447
import java.util.Optional;
48+
import java.util.Arrays;
4549
import java.util.function.BiConsumer;
4650

4751
@Singleton
@@ -551,6 +555,24 @@ private int deriveScenarioLoopTimes(ScenarioSpec scenario) {
551555
return scenarioLoopTimes;
552556
}
553557

558+
private int getParameterSize(Parameterized parameterized) {
559+
if (parameterized == null) {
560+
return 0;
561+
}
562+
563+
List<Object> valueSource = parameterized.getValueSource();
564+
List<String> csvSource = parameterized.getCsvSource();
565+
int csvSourceSize = 0;
566+
567+
if (csvSource != null && !csvSource.isEmpty()){
568+
String[] parsedHeaderLine = csvParser.parseLine(csvSource.get(0) + LINE_SEPARATOR);
569+
boolean hasHeader = parsedHeaderLine.length > 0 && Arrays.stream(parsedHeaderLine).allMatch(s -> s.matches("^\\|.*\\|$"));
570+
csvSourceSize = hasHeader ? csvSource.size() -1 : csvSource.size();
571+
}
572+
573+
return valueSource != null ? valueSource.size() : csvSourceSize;
574+
}
575+
554576
private List<FieldAssertionMatcher> compareStepResults(Step thisStep, String actualResult, String expectedResult, String resolvedScenarioState) {
555577
List<FieldAssertionMatcher> failureResults = new ArrayList<>();
556578

core/src/main/java/org/jsmart/zerocode/core/utils/RunnerUtils.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,6 @@ public static int loopCount(Step thisStep) {
120120
return stepLoopTimes > 0 ? stepLoopTimes: MIN_COUNT;
121121
}
122122

123-
public static int getParameterSize(Parameterized parameterized) {
124-
if (parameterized == null) {
125-
return 0;
126-
}
127-
128-
List<Object> valueSource = parameterized.getValueSource();
129-
List<String> csvSource = parameterized.getCsvSource();
130-
131-
return valueSource != null ? valueSource.size() :
132-
(csvSource != null ? csvSource.size() : 0);
133-
}
134-
135123
public static void handleTestCompleted(RunListener reportListener, Logger logger) {
136124
if (CHARTS_AND_CSV.equals(getProperty(ZEROCODE_JUNIT))) {
137125
/**

core/src/test/java/org/jsmart/zerocode/core/engine/preprocessor/ZeroCodeParameterizedProcessorImplTest.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package org.jsmart.zerocode.core.engine.preprocessor;
22

3+
import com.fasterxml.jackson.databind.JsonNode;
34
import com.fasterxml.jackson.databind.ObjectMapper;
45
import com.univocity.parsers.csv.CsvParser;
56
import jakarta.inject.Inject;
67
import org.jsmart.zerocode.core.di.main.ApplicationMainModule;
78
import org.jsmart.zerocode.core.domain.ScenarioSpec;
9+
import org.jsmart.zerocode.core.domain.Step;
810
import org.jsmart.zerocode.core.utils.SmartUtils;
911
import org.jukito.JukitoRunner;
1012
import org.jukito.TestModule;
@@ -75,7 +77,7 @@ public void testProcessParameterized_values() throws Exception {
7577
@Test
7678
public void testProcessParameterized_csv() throws Exception {
7779
String jsonDocumentAsString = smartUtils
78-
.getJsonDocumentAsString("unit_test_files/engine_unit_test_jsons/11_scenario_parameterized_csv.json");
80+
.getJsonDocumentAsString("unit_test_files/engine_unit_test_jsons/11.1_scenario_parameterized_csv.json");
7981
ScenarioSpec scenarioSpec = mapper.readValue(jsonDocumentAsString, ScenarioSpec.class);
8082

8183
ScenarioSpec scenarioSpecResolved = parameterizedProcessor.resolveParameterized(scenarioSpec, 0);
@@ -87,4 +89,23 @@ public void testProcessParameterized_csv() throws Exception {
8789
assertThat(scenarioSpecResolved.getSteps().get(0).getAssertions().get("status").asInt(), is(400));
8890

8991
}
92+
93+
@Test
94+
public void testProcessParameterized_csv_with_named_random() throws Exception {
95+
String jsonDocumentAsString = smartUtils
96+
.getJsonDocumentAsString("unit_test_files/engine_unit_test_jsons/11.2_scenario_parameterized_csv_with_named_random.json");
97+
ScenarioSpec scenarioSpec = mapper.readValue(jsonDocumentAsString, ScenarioSpec.class);
98+
99+
ScenarioSpec scenarioSpecResolved = parameterizedProcessor.resolveParameterized(scenarioSpec, 0);
100+
Step step = scenarioSpecResolved.getSteps().get(0);
101+
assertThat(step.getUrl(), is("/anUrl/${RANDOM.NUMBER}/${RANDOM.NUMBER}"));
102+
JsonNode queryParams = step.getRequest().get("queryParams");
103+
assertThat(queryParams.get("id1"), is(queryParams.get("id2")));
104+
assertThat(queryParams.get("addressId1"), is(queryParams.get("addressId2")));
105+
assertThat(scenarioSpecResolved.getSteps().get(0).getAssertions().get("status").asInt(), is(200));
106+
107+
scenarioSpecResolved = parameterizedProcessor.resolveParameterized(scenarioSpec, 1);
108+
assertThat(scenarioSpecResolved.getSteps().get(0).getUrl(), is("/anUrl/11/22"));
109+
assertThat(scenarioSpecResolved.getSteps().get(0).getAssertions().get("status").asInt(), is(400));
110+
}
90111
}

core/src/test/java/org/jsmart/zerocode/core/utils/SmartUtilsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void willGetJsonFileIntoA_JavaString() throws Exception {
7676
@Test
7777
public void willReadAllfileNamesFrom_TestResource() {
7878
List<String> allTestCaseFiles = SmartUtils.getAllEndPointFiles("unit_test_files/engine_unit_test_jsons");
79-
assertThat(allTestCaseFiles.size(), is(22));
79+
assertThat(allTestCaseFiles.size(), is(23));
8080
assertThat(allTestCaseFiles.get(0), is("unit_test_files/engine_unit_test_jsons/00_test_json_single_step_verifications.json"));
8181
}
8282

core/src/test/java/org/jsmart/zerocode/parameterized/ParameterisedCsvDemoTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@ public class ParameterisedCsvDemoTest {
1414
@JsonTestCase("integration_test_files/parameterized/parameterized_sample_csv_test.json")
1515
public void testParameterizedCsv() throws Exception {
1616
}
17+
18+
@Test
19+
@JsonTestCase("integration_test_files/parameterized/parameterized_sample_csv_with_headers_test.json")
20+
public void testParameterizedCsvWithHeaders() throws Exception {
21+
}
1722
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"scenarioName": "Parameterized test scenario demo",
3+
"steps": [
4+
{
5+
"name": "get_user",
6+
"url": "",
7+
"operation": "",
8+
"request": {
9+
"status": "${2}",
10+
"body": {
11+
"login": "octocat-${PARAM.id}-${PARAM.AddressId}"
12+
}
13+
},
14+
"assertions": {
15+
"status": "${$.get_user.response.status}",
16+
"body": {
17+
"login": "octocat-${PARAM.id}-${PARAM.AddressId}"
18+
}
19+
}
20+
}
21+
],
22+
"parameterized": {
23+
"csvSource":[
24+
"|id|, |AddressId|, |status|",
25+
"${RANDOM.NUMBER}, ${RANDOM.NUMBER}, 200",
26+
"11, 22, 400"
27+
]
28+
}
29+
}

core/src/test/resources/unit_test_files/engine_unit_test_jsons/11_scenario_parameterized_csv.json renamed to core/src/test/resources/unit_test_files/engine_unit_test_jsons/11.1_scenario_parameterized_csv.json

File renamed without changes.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"scenarioName": "For deserialize only",
3+
"ignoreStepFailures": true,
4+
"steps": [
5+
{
6+
"name": "step1",
7+
"url": "/anUrl/${0}/${1}",
8+
"operation": "GET",
9+
"request": {
10+
"queryParams": {
11+
"id1": "${PARAM.id}",
12+
"id2": "${PARAM.id}",
13+
"addressId1": "${PARAM.AddressId}",
14+
"addressId2": "${PARAM.AddressId}"
15+
}
16+
},
17+
"assertions": {
18+
"status": "${PARAM.status}"
19+
}
20+
}
21+
],
22+
"parameterized": {
23+
"csvSource": [
24+
"|id|, |AddressId|, |status|",
25+
"${RANDOM.NUMBER}, ${RANDOM.NUMBER}, 200",
26+
"11, 22, 400"
27+
]
28+
}
29+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.jsmart.zerocode.testhelp.tests.helloworldnamedcsvparam;
2+
3+
import org.jsmart.zerocode.core.domain.Scenario;
4+
import org.jsmart.zerocode.core.domain.TargetEnv;
5+
import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner;
6+
import org.junit.Test;
7+
import org.junit.runner.RunWith;
8+
9+
@TargetEnv("github_host.properties")
10+
@RunWith(ZeroCodeUnitRunner.class)
11+
public class HelloWorldNamedCsvParamsTest {
12+
13+
@Test
14+
@Scenario("parameterized_csv/hello_world_test_named_parameterized.json")
15+
public void testNamedParameterized() throws Exception {
16+
}
17+
18+
}

0 commit comments

Comments
 (0)