Skip to content

Commit b6ae652

Browse files
committed
feat: Add --mode positive/negative to run only positive or negative playbooks
1 parent 4dc134e commit b6ae652

14 files changed

Lines changed: 274 additions & 11 deletions

src/main/java/dev/dochia/cli/core/args/FilterArguments.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ public class FilterArguments {
6969
@Inject
7070
ProfileLoader profileLoader;
7171

72+
enum Mode {
73+
ALL, NEGATIVE, POSITIVE
74+
}
75+
7276
enum FieldType {
7377
STRING, NUMBER, INTEGER, BOOLEAN
7478
}
@@ -174,10 +178,42 @@ enum FormatType {
174178
description = "Path to custom profile configuration file (YAML)")
175179
private Path customProfileFile;
176180

181+
@CommandLine.Option(
182+
names = "--mode",
183+
description = "Playbook selection mode. Available values:%n" +
184+
" @|bold ALL|@ - Run all playbooks (default).%n" +
185+
" @|bold NEGATIVE|@ - Run only negative test scenarios (playbooks expecting 4XX responses: " +
186+
"validation, invalid values, authentication, etc). Excludes happy path playbooks.%n" +
187+
" @|bold POSITIVE|@ - Run only positive test scenarios (playbooks expecting 2XX responses: " +
188+
"happy path, valid examples, default values). Excludes validation error playbooks.",
189+
defaultValue = "ALL",
190+
showDefaultValue = CommandLine.Help.Visibility.ALWAYS
191+
)
192+
private Mode mode;
193+
177194

178195
private Map<String, List<String>> skipPathPlaybooks = new HashMap<>();
179196
private Map<String, Map<String, List<String>>> skipPlaybooksForExtensionMap = new HashMap<>();
180197

198+
199+
/**
200+
* Returns if DOCHIA should run only the negative playbooks.
201+
*
202+
* @return true if DOCHIA should run only the negative playbooks, false otherwise
203+
*/
204+
public boolean isOnly4xxPlaybooks() {
205+
return mode == Mode.NEGATIVE;
206+
}
207+
208+
/**
209+
* Returns if DOCHIA should run only the positive playbooks.
210+
*
211+
* @return true if DOCHIA should run only the positive playbooks, false otherwise
212+
*/
213+
public boolean isOnly2xxPlaybooks() {
214+
return mode == Mode.POSITIVE;
215+
}
216+
181217
/**
182218
* Gets the list of fields to skip during processing. If the list is not set, an empty list is returned.
183219
*

src/main/java/dev/dochia/cli/core/playbook/executor/FieldsIteratorExecutor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ private void executeTestCase(FieldsIteratorExecutorContext context, String fuzze
108108
testCaseListener.addExpectedResult(context.getLogger(), "Should return [{}]",
109109
context.getExpectedResponseCode() != null ? context.getExpectedResponseCode().asString() : "a response that doesn't match" + matchArguments.getMatchString());
110110

111+
if (!testCaseListener.shouldContinueExecution(context.getLogger(), context.getExpectedResponseCode())) {
112+
testCaseListener.skipTest(context.getLogger(), "Test skipped due to response code filtering");
113+
return;
114+
}
115+
111116
FuzzingResult fuzzingResult = this.getFuzzingResult(context, fuzzedField, strategy);
112117

113118
HttpResponse response = serviceCaller.call(

src/main/java/dev/dochia/cli/core/playbook/executor/HeadersIteratorExecutor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public void execute(HeadersIteratorExecutorContext context) {
7070
testCaseListener.addExpectedResult(context.getLogger(), "Should return [{}]",
7171
expectedResponseCode != null ? expectedResponseCode.asString() : "a response that doesn't match" + matchArguments.getMatchString());
7272

73+
if (!testCaseListener.shouldContinueExecution(context.getLogger(), expectedResponseCode)) {
74+
testCaseListener.skipTest(context.getLogger(), "Test skipped due to response code filtering");
75+
return;
76+
}
77+
7378
ServiceData serviceData = ServiceData.builder()
7479
.relativePath(context.getPlaybookData().getPath())
7580
.contractPath(context.getPlaybookData().getContractPath())

src/main/java/dev/dochia/cli/core/playbook/executor/SimpleExecutor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ public void execute(SimpleExecutorContext context) {
5656
testCaseListener.addScenario(context.getLogger(), context.getScenario());
5757
testCaseListener.addExpectedResult(context.getLogger(), "Should return {}" + context.getExpectedResult(), context.getExpectedSpecificResponseCode());
5858

59+
if (!testCaseListener.shouldContinueExecution(context.getLogger(), context.getExpectedResponseCode())) {
60+
testCaseListener.skipTest(context.getLogger(), "Test skipped due to response code filtering");
61+
return;
62+
}
63+
5964
HttpResponse response = serviceCaller.call(
6065
ServiceData.builder()
6166
.relativePath(context.getPath())

src/main/java/dev/dochia/cli/core/playbook/field/DuplicateKeysFieldsPlaybook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ private void runDuplicationTestCase(PlaybookData data, String field, String dupl
121121
testCaseListener.addExpectedResult(logger,
122122
"Service should return a [{}] response", ResponseCodeFamilyPredefined.FOURXX.asString());
123123

124+
if (!testCaseListener.shouldContinueExecution(logger, ResponseCodeFamilyPredefined.FOURXX)) {
125+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
126+
return;
127+
}
128+
124129
HttpResponse response = serviceCaller.call(buildServiceData(data, duplicatedPayload));
125130
testCaseListener.reportResult(logger, data, response, ResponseCodeFamilyPredefined.FOURXX);
126131
}

src/main/java/dev/dochia/cli/core/playbook/field/InsertWhitespacesInFieldNamesFieldPlaybook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ private void process(PlaybookData data, String field, String randomWhitespace) {
5959
testCaseListener.addScenario(logger, "Insert random whitespaces in the field name [{}]", field);
6060
testCaseListener.addExpectedResult(logger, "Should get a [{}] response code", ResponseCodeFamilyPredefined.FOURXX);
6161

62+
if (!testCaseListener.shouldContinueExecution(logger, ResponseCodeFamilyPredefined.FOURXX)) {
63+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
64+
return;
65+
}
66+
6267
String fuzzedJson = JsonUtils.insertCharactersInFieldKey(data.getPayload(), field, randomWhitespace);
6368

6469
HttpResponse response = serviceCaller.call(ServiceData.builder().relativePath(data.getPath()).headers(data.getHeaders())

src/main/java/dev/dochia/cli/core/playbook/field/NewFieldsPlaybook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ private void process(PlaybookData data) {
6262
testCaseListener.addScenario(logger, "Add new field inside the request: name [{}], value [{}]. All other details are similar to a happy flow", NEW_FIELD, NEW_FIELD);
6363
testCaseListener.addExpectedResult(logger, "Should get a [{}] response code", expectedResultCode.asString());
6464

65+
if (!testCaseListener.shouldContinueExecution(logger, expectedResultCode)) {
66+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
67+
return;
68+
}
69+
6570
HttpResponse response = serviceCaller.call(ServiceData.builder().relativePath(data.getPath()).headers(data.getHeaders())
6671
.payload(fuzzedJson).queryParams(data.getQueryParams()).httpMethod(data.getMethod()).contractPath(data.getContractPath())
6772
.contentType(data.getFirstRequestContentType()).pathParamsPayload(data.getPathParamsPayload())

src/main/java/dev/dochia/cli/core/playbook/field/RemoveFieldsPlaybook.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dev.dochia.cli.core.args.FilterArguments;
44
import dev.dochia.cli.core.args.ProcessingArguments;
55
import dev.dochia.cli.core.http.HttpMethod;
6+
import dev.dochia.cli.core.http.ResponseCodeFamily;
67
import dev.dochia.cli.core.http.ResponseCodeFamilyPredefined;
78
import dev.dochia.cli.core.io.ServiceCaller;
89
import dev.dochia.cli.core.io.ServiceData;
@@ -89,8 +90,12 @@ private void process(PlaybookData data, List<String> required, Set<String> subse
8990
testCaseListener.addScenario(logger, "Remove the following fields from request: {}", subset);
9091

9192
boolean hasRequiredFieldsRemove = this.hasRequiredFieldsRemove(required, subset);
93+
ResponseCodeFamily expectedResponseCode = ResponseCodeFamilyPredefined.getResultCodeBasedOnRequiredFieldsRemoved(hasRequiredFieldsRemove);
9294
testCaseListener.addExpectedResult(logger, "Should return [{}] response code as required fields [{}] removed", ResponseCodeFamilyPredefined.getExpectedWordingBasedOnRequiredFields(hasRequiredFieldsRemove));
93-
95+
if (!testCaseListener.shouldContinueExecution(logger, expectedResponseCode)) {
96+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
97+
return;
98+
}
9499
HttpResponse response = serviceCaller.call(ServiceData.builder().relativePath(data.getPath()).headers(data.getHeaders())
95100
.payload(finalJsonPayload).queryParams(data.getQueryParams()).httpMethod(data.getMethod()).contractPath(data.getContractPath())
96101
.contentType(data.getFirstRequestContentType()).pathParamsPayload(data.getPathParamsPayload()).build());

src/main/java/dev/dochia/cli/core/playbook/field/ZeroWidthCharsInNamesFieldsPlaybook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ private void process(PlaybookData data, String fuzzedField, String fuzzValue) {
6464
fuzzedField, FuzzingStrategy.formatValue(fuzzValue));
6565
testCaseListener.addExpectedResult(logger, "Should get a [{}] response code", ResponseCodeFamilyPredefined.FOURXX.asString());
6666

67+
if (!testCaseListener.shouldContinueExecution(logger, ResponseCodeFamilyPredefined.FOURXX)) {
68+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
69+
return;
70+
}
71+
6772
HttpResponse response = serviceCaller.call(ServiceData.builder().relativePath(data.getPath()).headers(data.getHeaders())
6873
.payload(fuzzedPayload).queryParams(data.getQueryParams()).httpMethod(data.getMethod()).contractPath(data.getContractPath())
6974
.contentType(data.getFirstRequestContentType()).pathParamsPayload(data.getPathParamsPayload())

src/main/java/dev/dochia/cli/core/playbook/field/base/BaseFieldsPlaybook.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ protected void process(PlaybookData data, String fuzzedField, FuzzingStrategy fu
134134
testCaseListener.addExpectedResult(
135135
logger, "Should return [{}]", expectedResponseCodeBasedOnConstraints.asString());
136136

137+
if (!testCaseListener.shouldContinueExecution(logger, expectedResponseCodeBasedOnConstraints)) {
138+
testCaseListener.skipTest(logger, "Test skipped due to response code filtering");
139+
return;
140+
}
141+
137142
HttpResponse response = serviceCaller.call(serviceData);
138143

139144
testCaseListener.reportResult(

0 commit comments

Comments
 (0)