Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
rebugged authored Nov 11, 2020
2 parents 8f26a17 + df49725 commit 351af71
Show file tree
Hide file tree
Showing 23 changed files with 198 additions and 37 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ Introduction
===
Zerocode Open Source is a lightweight, simple and extensible framework for writing test intentions in a simple JSON or YAML format that facilitates both declarative configuration and automation.

Put simply, Zerocode solves API Development pain points and brings simplicity to API automation. The framework provides a unified solution to manage response validations, target API invocations, perform load/stress testing and perform security testing using a the simple domain specific languages (DSL) JSON and YAML.
Put simply, Zerocode is a sollution for all API Development pain points. The objective is to bring simplicity to API automation. The framework provides a unified solution to manage response validations, target API invocations, perform load/stress testing and perform security testing using a the simple domain specific languages (DSL) JSON and YAML.

For example, if your REST API URL `https://localhost:8080/api/v1/customers/123` with `GET` method and `"Content-Type": "application/json"` returns the following payload and a `http` status code `200(OK)` ,
For example, if your REST API URL `https://localhost:8080/api/v1/customers/123` with `GET` method and `"Content-Type": "application/json"` returns the following payload and a `http` status code `200(OK)` ,
```javaScript
Response:
{
Expand Down
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>zerocode-tdd-parent</artifactId>
<groupId>org.jsmart</groupId>
<version>1.3.25-SNAPSHOT</version>
<version>1.3.27-SNAPSHOT</version>
</parent>

<artifactId>zerocode-tdd</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jsmart.zerocode.core.engine.executor;

import org.jsmart.zerocode.core.engine.preprocessor.ScenarioExecutionState;

public interface ApiServiceExecutor {
/**
*
Expand All @@ -25,8 +27,9 @@ public interface ApiServiceExecutor {
* @param kafkaTopic Kafka topic(s) residing on the brokers
* @param methodName A produce or consume or poll operation
* @param requestJson RAW or JSON records for producing, config settings for consuming
* @param scenarioExecutionState The state of the scenario execution
* @return String The broker acknowledgement in JSON
*/
String executeKafkaService(String kafkaServers, String kafkaTopic, String methodName, String requestJson);
String executeKafkaService(String kafkaServers, String kafkaTopic, String methodName, String requestJson, ScenarioExecutionState scenarioExecutionState);

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.google.inject.name.Named;
import org.jsmart.zerocode.core.engine.executor.httpapi.HttpApiExecutor;
import org.jsmart.zerocode.core.engine.executor.javaapi.JavaMethodExecutor;
import org.jsmart.zerocode.core.engine.preprocessor.ScenarioExecutionState;
import org.jsmart.zerocode.core.kafka.client.BasicKafkaClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -54,7 +55,7 @@ public String executeJavaOperation(String className, String methodName, String r
}

@Override
public String executeKafkaService(String kafkaServers, String kafkaTopic, String operation, String requestJson) {
return kafkaClient.execute(kafkaServers, kafkaTopic, operation, requestJson);
public String executeKafkaService(String kafkaServers, String kafkaTopic, String operation, String requestJson, ScenarioExecutionState scenarioExecutionState) {
return kafkaClient.execute(kafkaServers, kafkaTopic, operation, requestJson, scenarioExecutionState);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,14 @@ void digReplaceContent(Map<String, Object> map) {
if (token != null && token.startsWith(JSON_PAYLOAD_FILE)) {
String resourceJsonFile = token.substring(JSON_PAYLOAD_FILE.length());
try {
Object jsonFileContent = objectMapper.readTree(readJsonAsString(resourceJsonFile));
entry.setValue(jsonFileContent);
JsonNode jsonNode = objectMapper.readTree(readJsonAsString(resourceJsonFile));
if (jsonNode.isObject()) {
//also replace content of just read json file (recursively)
final Map<String, Object> jsonFileContent = objectMapper.convertValue(jsonNode, Map.class);
digReplaceContent(jsonFileContent);
jsonNode = objectMapper.convertValue(jsonFileContent, JsonNode.class);
}
entry.setValue(jsonNode);
} catch (Exception exx) {
LOGGER.error("External file reference exception - {}", exx.getMessage());
throw new RuntimeException(exx);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jsmart.zerocode.core.kafka.client;

import com.google.inject.Inject;
import org.jsmart.zerocode.core.engine.preprocessor.ScenarioExecutionState;
import org.jsmart.zerocode.core.kafka.receive.KafkaReceiver;
import org.jsmart.zerocode.core.kafka.send.KafkaSender;
import org.slf4j.Logger;
Expand All @@ -19,7 +20,7 @@ public class BasicKafkaClient {
public BasicKafkaClient() {
}

public String execute(String brokers, String topicName, String operation, String requestJson) {
public String execute(String brokers, String topicName, String operation, String requestJson, ScenarioExecutionState scenarioExecutionState) {
LOGGER.info("brokers:{}, topicName:{}, operation:{}, requestJson:{}", brokers, topicName, operation, requestJson);

try {
Expand All @@ -28,7 +29,7 @@ public String execute(String brokers, String topicName, String operation, String
case "load":
case "publish":
case "produce":
return sender.send(brokers, topicName, requestJson);
return sender.send(brokers, topicName, requestJson, scenarioExecutionState);

case "unload":
case "consume":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,33 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.apache.kafka.clients.producer.Callback;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.clients.producer.RecordMetadata;
import org.jsmart.zerocode.core.di.provider.GsonSerDeProvider;
import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider;
import org.jsmart.zerocode.core.engine.preprocessor.ScenarioExecutionState;
import org.jsmart.zerocode.core.engine.preprocessor.ZeroCodeAssertionsProcessorImpl;
import org.jsmart.zerocode.core.kafka.delivery.DeliveryDetails;
import org.jsmart.zerocode.core.kafka.send.message.ProducerJsonRecord;
import org.jsmart.zerocode.core.kafka.send.message.ProducerJsonRecords;
import org.jsmart.zerocode.core.kafka.send.message.ProducerRawRecords;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static org.jsmart.zerocode.core.constants.ZerocodeConstants.FAILED;
import static org.jsmart.zerocode.core.constants.ZerocodeConstants.OK;
import static org.jsmart.zerocode.core.kafka.KafkaConstants.JSON;
import static org.jsmart.zerocode.core.kafka.KafkaConstants.RAW;
import static org.jsmart.zerocode.core.kafka.KafkaConstants.PROTO;
import static org.jsmart.zerocode.core.kafka.KafkaConstants.RAW;
import static org.jsmart.zerocode.core.kafka.KafkaConstants.RECORD_TYPE_JSON_PATH;
import static org.jsmart.zerocode.core.kafka.helper.KafkaProducerHelper.createProducer;
import static org.jsmart.zerocode.core.kafka.helper.KafkaProducerHelper.prepareJsonRecordToSend;
Expand All @@ -46,10 +49,13 @@ public class KafkaSender {
@Named("kafka.producer.properties")
private String producerPropertyFile;

@Inject
private ZeroCodeAssertionsProcessorImpl zeroCodeAssertionsProcessor;

private final ObjectMapper objectMapper = new ObjectMapperProvider().get();
private final Gson gson = new GsonSerDeProvider().get();

public String send(String brokers, String topicName, String requestJson) throws JsonProcessingException {
public String send(String brokers, String topicName, String requestJson, ScenarioExecutionState scenarioExecutionState) throws JsonProcessingException {
Producer<?, ?> producer = createProducer(brokers, producerPropertyFile);
String deliveryDetails = null;

Expand All @@ -73,7 +79,7 @@ public String send(String brokers, String topicName, String requestJson) throws
LOGGER.info("From file:'{}', Sending record number: {}\n", fileName, i);
deliveryDetails = sendRaw(topicName, producer, record, rawRecords.getAsync());
}
} catch(Throwable ex) {
} catch (Throwable ex) {
throw new RuntimeException(ex);
}
} else {
Expand All @@ -86,7 +92,7 @@ public String send(String brokers, String topicName, String requestJson) throws
}

break;
case PROTO:
case PROTO:
case JSON:
jsonRecords = objectMapper.readValue(requestJson, ProducerJsonRecords.class);

Expand All @@ -96,16 +102,18 @@ public String send(String brokers, String topicName, String requestJson) throws
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
for (int i = 0; (line = br.readLine()) != null; i++) {
line = zeroCodeAssertionsProcessor.resolveStringJson(line,
scenarioExecutionState.getResolvedScenarioState());
ProducerJsonRecord record = objectMapper.readValue(line, ProducerJsonRecord.class);
LOGGER.info("From file:'{}', Sending record number: {}\n", fileName, i);
deliveryDetails = sendJson(topicName, producer, record, jsonRecords.getAsync(),recordType,requestJson);
deliveryDetails = sendJson(topicName, producer, record, jsonRecords.getAsync(), recordType, requestJson);
}
}
} else {
List<ProducerJsonRecord> records = jsonRecords.getRecords();
validateProduceRecord(records);
for (int i = 0; i < records.size(); i++) {
deliveryDetails = sendJson(topicName, producer, records.get(i), jsonRecords.getAsync(),recordType,requestJson);
deliveryDetails = sendJson(topicName, producer, records.get(i), jsonRecords.getAsync(), recordType, requestJson);
}
}

Expand Down Expand Up @@ -159,7 +167,7 @@ private String sendJson(String topicName,
Boolean isAsync,
String recordType,
String requestJson) throws InterruptedException, ExecutionException {
ProducerRecord record = prepareJsonRecordToSend(topicName, recordToSend,recordType, requestJson);
ProducerRecord record = prepareJsonRecordToSend(topicName, recordToSend, recordType, requestJson);

RecordMetadata metadata;
if (Boolean.TRUE.equals(isAsync)) {
Expand All @@ -182,13 +190,12 @@ private String sendJson(String topicName,
return deliveryDetails;
}



private File validateAndGetFile(String fileName) {
try{
private File validateAndGetFile(String fileName) {
try {
URL resource = getClass().getClassLoader().getResource(fileName);
return new File(resource.getFile());
} catch(Exception ex) {
} catch (Exception ex) {
throw new RuntimeException("Error accessing file: `" + fileName + "' - " + ex);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ private String executeApi(String logPrefixRelationshipId,
.request(prettyPrintJson(resolvedRequestJson));

String topicName = url.substring(KAFKA_TOPIC.length());
executionResult = apiExecutor.executeKafkaService(kafkaServers, topicName, operationName, resolvedRequestJson);
executionResult = apiExecutor.executeKafkaService(kafkaServers, topicName, operationName, resolvedRequestJson, scenarioExecutionState);
break;

case NONE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ public void test_deepHashMapTraverse() throws IOException {
assertThat(read(resultJson, "$.assertions.body.age"), is(16));
}

@Test
public void test_deepRecursiveFile() throws IOException {
String jsonAsString = readJsonAsString("unit_test_files/filebody_unit_test/json_step_test_file_recursive.json");
Map<String, Object> map = objectMapper.readValue(jsonAsString, new TypeReference<Map<String, Object>>() {});

externalFileProcessor.digReplaceContent(map);
String resultJson = objectMapper.writeValueAsString(map);

assertThat(read(resultJson, "$.request.body.addresses[0].type"), is("corp-office"));
assertThat(read(resultJson, "$.request.body.addresses[1].type"), is("hr-office"));
}

@Test
public void test_addressArray() throws IOException {
String jsonAsString = readJsonAsString("unit_test_files/filebody_unit_test/json_step_test_address_array.json");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"id": "Emp-No-${RANDOM.NUMBER}",
"age": 16,
"secret": "passwwrd",
"addresses": "${JSON.FILE:unit_test_files/filebody_unit_test/common/comm_addresses.json}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "create_emp",
"url": "/api/test/v1/employess",
"operation": "POST",
"request": {
"headers": "${JSON.FILE:unit_test_files/filebody_unit_test/common/common_content.json}",
"body": "${JSON.FILE:unit_test_files/filebody_unit_test/common/common_content_recursive.json}"
},
"assertions": {
"status": 201,
"body": "${JSON.FILE:unit_test_files/filebody_unit_test/common/common_content.json}"
}
}
10 changes: 7 additions & 3 deletions http-testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>zerocode-tdd-parent</artifactId>
<groupId>org.jsmart</groupId>
<version>1.3.25-SNAPSHOT</version>
<version>1.3.27-SNAPSHOT</version>
</parent>

<groupId>org.jsmart</groupId>
Expand All @@ -16,7 +16,6 @@

<properties>
<java.version>1.8</java.version>
<micro-simulator.version>1.1.8</micro-simulator.version>
</properties>

<dependencies>
Expand All @@ -33,11 +32,16 @@
The below "micro-simulator" dependency is not needed for real live projects.
This is used here just to mock/stub some end points for demo purpose only.
-->
<dependency>
<!--<dependency>
<groupId>org.jsmart</groupId>
<artifactId>micro-simulator</artifactId>
<version>${micro-simulator.version}</version>
<scope>test</scope>
</dependency>-->
<dependency>
<groupId>org.jsmart</groupId>
<artifactId>micro-simulator</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public class HelloReuseJsonFileAsContentTest {
public void testHelloWorld_jsonFileAsBody() throws Exception {
}

@Test
@JsonTestCase("helloworld_ext_file_json/hello_world_jsonfile_as_request_body_with_inner_ref.json")
public void testHelloWorld_jsonFileAsBody_inception() throws Exception {
}

@Test
@JsonTestCase("helloworld_ext_file_json/hello_world_jsonfile_as_response_body.json")
public void testHello_jsonFileAsResponseBody() throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"scenarioName": "POST API - File json as request content - Reuse body",
"steps": [
{
"name": "create_emp",
"url": "/api/v1/employees",
"method": "POST",
"request": {
"body" : "${JSON.FILE:reusable_content/request/request_body_with_address.json}"
},
"assertions": {
"status": 201
}
},
{
"name": "get_user_details",
"url": "/api/v1/employees/${$.create_emp.response.body.id}",
"method": "GET",
"request": {
},
"assertions": {
"status": 200,
"body": {
"id": 39001,
"ldapId": "emmanorton",
"name": "Emma",
"surName": "Norton"
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Emma",
"surName": "Norton",
"address": "${JSON.FILE:reusable_content/request/office_address.json}"
}
2 changes: 1 addition & 1 deletion junit5-testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>zerocode-tdd-parent</artifactId>
<groupId>org.jsmart</groupId>
<version>1.3.25-SNAPSHOT</version>
<version>1.3.27-SNAPSHOT</version>
</parent>

<artifactId>zerocode-tdd-jupiter</artifactId>
Expand Down
2 changes: 1 addition & 1 deletion kafka-testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>zerocode-tdd-parent</artifactId>
<groupId>org.jsmart</groupId>
<version>1.3.25-SNAPSHOT</version>
<version>1.3.27-SNAPSHOT</version>
</parent>

<artifactId>kafka-testing</artifactId>
Expand Down
Loading

0 comments on commit 351af71

Please sign in to comment.