diff --git a/.gitignore b/.gitignore index 302c16c4f..1b257ebfb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ hs_err_pid* *.idea /target .DS_Store - +package.properties #for eclipse .classpath diff --git a/core/pom.xml b/core/pom.xml index 817d0515a..da24ec24c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -63,6 +63,22 @@ + + org.junit.vintage + junit-vintage-engine + + + org.junit.jupiter + junit-jupiter-params + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.platform + junit-platform-runner + com.google.code.gson gson diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/LoadWith.java b/core/src/main/java/org/jsmart/zerocode/core/domain/LoadWith.java index f41b542e4..6bf5b30b4 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/LoadWith.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/LoadWith.java @@ -1,12 +1,9 @@ package org.jsmart.zerocode.core.domain; -import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface LoadWith { String value(); } \ No newline at end of file diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/TestMapping.java b/core/src/main/java/org/jsmart/zerocode/core/domain/TestMapping.java index c279ed7b8..4aaafd181 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/TestMapping.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/TestMapping.java @@ -1,10 +1,11 @@ package org.jsmart.zerocode.core.domain; -import java.lang.annotation.*; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) @Repeatable( value = TestMappings.class ) public @interface TestMapping { Class testClass(); diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/TestMappings.java b/core/src/main/java/org/jsmart/zerocode/core/domain/TestMappings.java index ee1280fe0..75283f57b 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/TestMappings.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/TestMappings.java @@ -1,12 +1,9 @@ package org.jsmart.zerocode.core.domain; -import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface TestMappings { public TestMapping[] value() default {}; diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilder.java b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilder.java similarity index 88% rename from core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilder.java rename to core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilder.java index b10841ab8..67c74e522 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilder.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilder.java @@ -18,8 +18,8 @@ import static org.jsmart.zerocode.core.domain.reports.ZeroCodeReportProperties.TARGET_REPORT_DIR; import static org.slf4j.LoggerFactory.getLogger; -public class ZeroCodeReportBuilder { - private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeReportBuilder.class); +public class ZeroCodeExecResultIoWriteBuilder { + private static final org.slf4j.Logger LOGGER = getLogger(ZeroCodeExecResultIoWriteBuilder.class); public static final int REPORT_WRITING_THREAD_POOL = 5; private LocalDateTime timeStamp; @@ -28,8 +28,8 @@ public class ZeroCodeReportBuilder { private ExecutorService executorService = Executors.newFixedThreadPool(REPORT_WRITING_THREAD_POOL); - public static ZeroCodeReportBuilder newInstance() { - return new ZeroCodeReportBuilder(); + public static ZeroCodeExecResultIoWriteBuilder newInstance() { + return new ZeroCodeExecResultIoWriteBuilder(); } public ZeroCodeReport build() { @@ -39,17 +39,17 @@ public ZeroCodeReport build() { return built; } - public ZeroCodeReportBuilder timeStamp(LocalDateTime timeStamp) { + public ZeroCodeExecResultIoWriteBuilder timeStamp(LocalDateTime timeStamp) { this.timeStamp = timeStamp; return this; } - public ZeroCodeReportBuilder results(List results) { + public ZeroCodeExecResultIoWriteBuilder results(List results) { this.results = results; return this; } - public ZeroCodeReportBuilder result(ZeroCodeExecResult result) { + public ZeroCodeExecResultIoWriteBuilder result(ZeroCodeExecResult result) { this.results.add(result); return this; } diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportStepBuilder.java b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportStepBuilder.java index 70e2fff55..27473c0a8 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportStepBuilder.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportStepBuilder.java @@ -17,6 +17,7 @@ public class ZeroCodeReportStepBuilder { String request; String response; String id; + String assertions; public static ZeroCodeReportStepBuilder newInstance() { return new ZeroCodeReportStepBuilder(); @@ -27,7 +28,7 @@ public ZeroCodeReportStep build() { loop, name, url, correlationId, operation, requestTimeStamp, responseTimeStamp, responseDelay, result, - request, response); + request, response, assertions); return built; } @@ -86,6 +87,11 @@ public ZeroCodeReportStepBuilder result(String result) { return this; } + public ZeroCodeReportStepBuilder assertions(String assertions) { + this.assertions = assertions; + return this; + } + public ZeroCodeReportStepBuilder id(String id) { this.id = id; return this; diff --git a/core/src/main/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportStep.java b/core/src/main/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportStep.java index 1c43e8ea8..d9711cc94 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportStep.java +++ b/core/src/main/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportStep.java @@ -24,21 +24,22 @@ public class ZeroCodeReportStep { private final String result; private final String request; private final String response; + private final String assertions; @JsonCreator public ZeroCodeReportStep( - @JsonProperty("stepLoop")Integer loop, - @JsonProperty("name")String name, - @JsonProperty("url")String url, - @JsonProperty("correlationId")String correlationId, - @JsonProperty("operation")String operation, - @JsonProperty("requestTimeStamp")LocalDateTime requestTimeStamp, - @JsonProperty("responseTimeStamp")LocalDateTime responseTimeStamp, - @JsonProperty("responseDelay")Double responseDelay, - @JsonProperty("result")String result, - @JsonProperty("request")String request, - @JsonProperty("response")String response - ) { + @JsonProperty("stepLoop") Integer loop, + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("correlationId") String correlationId, + @JsonProperty("operation") String operation, + @JsonProperty("requestTimeStamp") LocalDateTime requestTimeStamp, + @JsonProperty("responseTimeStamp") LocalDateTime responseTimeStamp, + @JsonProperty("responseDelay") Double responseDelay, + @JsonProperty("result") String result, + @JsonProperty("request") String request, + @JsonProperty("response") String response, + @JsonProperty("assertions") String assertions) { this.loop = loop; this.name = name; this.url = url; @@ -50,6 +51,7 @@ public ZeroCodeReportStep( this.result = result; this.request = request; this.response = response; + this.assertions = assertions; } public Integer getLoop() { @@ -92,14 +94,14 @@ public String getRequest() { return request; } -// public JsonNode getRequest() throws IOException { -// return new ObjectMapperProvider().get().readTree(request); -// } - public String getResponse() { return response; } + public String getAssertions() { + return assertions; + } + @Override public String toString() { return "ZeroCodeReportStep{" + @@ -114,6 +116,7 @@ public String toString() { ", result='" + result + '\'' + ", request='" + request + '\'' + ", response='" + response + '\'' + + ", assertions='" + assertions + '\'' + '}'; } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/engine/listener/ZeroCodeTestReportJupiterListener.java b/core/src/main/java/org/jsmart/zerocode/core/engine/listener/ZeroCodeTestReportJupiterListener.java new file mode 100644 index 000000000..eefe364d7 --- /dev/null +++ b/core/src/main/java/org/jsmart/zerocode/core/engine/listener/ZeroCodeTestReportJupiterListener.java @@ -0,0 +1,101 @@ +package org.jsmart.zerocode.core.engine.listener; + +import java.time.LocalDateTime; +import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultBuilder; +import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultIoWriteBuilder; +import org.jsmart.zerocode.core.logbuilder.LogCorrelationshipPrinter; +import org.junit.platform.engine.TestExecutionResult; +import org.junit.platform.launcher.TestExecutionListener; +import org.junit.platform.launcher.TestIdentifier; +import org.junit.platform.launcher.TestPlan; +import org.slf4j.Logger; + +import static java.time.LocalDateTime.now; +import static org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultBuilder.newInstance; +import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * This class correlates between request and response of a test and creates easily traceable logs. + * Here, for each JUnit5 parallel tests this can be interpreted the following way- + * - a) Request timestamp - When the test started execution + * - b) Response timestamp - When the test finished execution + * - c) Response Delay(milli second) - (b-a) milli seconds + * - d) Scenario: Fully qualified name of the Test-Class + * - e) Step: Name of the Test-Method in the above Test-Class with @Test(jupiter package) + * + * Later the logs are written to the target folder as raw JSON files ready for rendering + * CSV-reports and Html-Chart/Dashboards + * + * @author Nirmal Chandra on 25-apr-2019 + */ +public class ZeroCodeTestReportJupiterListener implements TestExecutionListener { + private static final Logger LOGGER = getLogger(ZeroCodeTestReportJupiterListener.class); + + private final Class testClass; + private final String testMethod; + private String testDescription; + + private LogCorrelationshipPrinter correlationshipPrettyLogger; + private String logPrefixRelationshipId; + private boolean passed=true; + + public ZeroCodeTestReportJupiterListener(Class testClass, String testMethod) { + this.testClass = testClass; + this.testMethod = testMethod; + this.testDescription = testClass + "#" + testMethod; + } + + @Override + public void testPlanExecutionStarted(TestPlan testPlan) { + logPrefixRelationshipId = prepareRequestReport(testDescription); + } + + @Override + public void testPlanExecutionFinished(TestPlan testPlan) { + prepareResponseReport(logPrefixRelationshipId); + buildReportAndPrintToFile(testDescription); + } + + @Override + public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { + if(testExecutionResult.getStatus().equals(FAILED)){ + passed = false; + } + } + + private String prepareRequestReport(String description) { + correlationshipPrettyLogger = LogCorrelationshipPrinter.newInstance(LOGGER); + correlationshipPrettyLogger.stepLoop(0); + final String logPrefixRelationshipId = correlationshipPrettyLogger.createRelationshipId(); + LocalDateTime timeNow = now(); + correlationshipPrettyLogger.aRequestBuilder() + .stepLoop(0) + .relationshipId(logPrefixRelationshipId) + .requestTimeStamp(timeNow) + .step(testMethod); + LOGGER.info("JUnit5 *requestTimeStamp:{}, \nJUnit Request:{}", timeNow, logPrefixRelationshipId); + return logPrefixRelationshipId; + } + + private void prepareResponseReport(String logPrefixRelationshipId) { + LocalDateTime timeNow = now(); + LOGGER.info("JUnit5 *responseTimeStamp:{}, \nJUnit Response:{}", timeNow, logPrefixRelationshipId); + correlationshipPrettyLogger.aResponseBuilder() + .relationshipId(logPrefixRelationshipId) + .responseTimeStamp(timeNow); + correlationshipPrettyLogger.result(passed); + correlationshipPrettyLogger.buildResponseDelay(); + } + + private void buildReportAndPrintToFile(String description) { + ZeroCodeExecResultBuilder reportResultBuilder = newInstance().loop(0).scenarioName(testClass.getName()); + reportResultBuilder.step(correlationshipPrettyLogger.buildReportSingleStep()); + + ZeroCodeExecResultIoWriteBuilder reportBuilder = ZeroCodeExecResultIoWriteBuilder.newInstance().timeStamp(now()); + reportBuilder.result(reportResultBuilder.build()); + + reportBuilder.printToFile(description + correlationshipPrettyLogger.getCorrelationId() + ".json"); + } + +} \ No newline at end of file diff --git a/core/src/main/java/org/jsmart/zerocode/core/logbuilder/LogCorrelationshipPrinter.java b/core/src/main/java/org/jsmart/zerocode/core/logbuilder/LogCorrelationshipPrinter.java index a23f1adbf..bd0d66d93 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/logbuilder/LogCorrelationshipPrinter.java +++ b/core/src/main/java/org/jsmart/zerocode/core/logbuilder/LogCorrelationshipPrinter.java @@ -61,14 +61,13 @@ public ZeroCodeReportStep buildReportSingleStep() { ZeroCodeReportStepBuilder zeroCodeReportStep = ZeroCodeReportStepBuilder.newInstance() //.request(requestLogBuilder.request) //TODO //.response(responseLogBuilder.response) //TODO - //.assertions() .loop(stepLoop) .name(requestLogBuilder.getStepName()) .correlationId(getCorrelationId()) .result(result == true? RESULT_PASS : RESULT_FAIL) .url(requestLogBuilder.getUrl()) .operation(requestLogBuilder.getMethod()) - .result(responseLogBuilder.getAssertion()) + .assertions(responseLogBuilder.getAssertion()) .requestTimeStamp(requestLogBuilder.getRequestTimeStamp()) .responseTimeStamp(responseLogBuilder.responseTimeStamp) .responseDelay(responseDelay) diff --git a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java index 40f4b6943..45377ec5d 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImpl.java @@ -69,8 +69,7 @@ public class ZeroCodeReportGeneratorImpl implements ZeroCodeReportGenerator { @Named("interactive.html.report.disabled") private boolean interactiveHtmlReportDisabled; - @Inject - private ObjectMapper mapper; + private final ObjectMapper mapper; private List treeReports; @@ -78,7 +77,9 @@ public class ZeroCodeReportGeneratorImpl implements ZeroCodeReportGenerator { private List csvRows = new ArrayList<>(); - public ZeroCodeReportGeneratorImpl() { + @Inject + public ZeroCodeReportGeneratorImpl(ObjectMapper mapper) { + this.mapper = mapper; } @Override @@ -114,7 +115,7 @@ public void generateExtentReport() { step.info(MarkupHelper.createCodeBlock(thisStep.getOperation() + "\t" + thisStep.getUrl())); step.info(MarkupHelper.createCodeBlock(thisStep.getRequest(), CodeLanguage.JSON)); step.info(MarkupHelper.createCodeBlock(thisStep.getResponse(), CodeLanguage.JSON)); - step.fail(MarkupHelper.createCodeBlock("Reason:\n" + thisStep.getResult())); + step.fail(MarkupHelper.createCodeBlock("Reason:\n" + thisStep.getAssertions())); } extentReports.flush(); }); diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java index 83c987a25..b46988c84 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeMultiStepsScenarioRunnerImpl.java @@ -9,7 +9,7 @@ import org.jsmart.zerocode.core.domain.ScenarioSpec; import org.jsmart.zerocode.core.domain.Step; import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultBuilder; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeReportBuilder; +import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultIoWriteBuilder; import org.jsmart.zerocode.core.engine.assertion.AssertionReport; import org.jsmart.zerocode.core.engine.assertion.JsonAsserter; import org.jsmart.zerocode.core.engine.executor.JsonServiceExecutor; @@ -72,7 +72,7 @@ public class ZeroCodeMultiStepsScenarioRunnerImpl implements ZeroCodeMultiStepsS private static StepNotificationHandler notificationHandler = new StepNotificationHandler(); - private ZeroCodeReportBuilder reportBuilder; + private ZeroCodeExecResultIoWriteBuilder reportBuilder; private ZeroCodeExecResultBuilder reportResultBuilder; @@ -83,7 +83,7 @@ public synchronized boolean runScenario(ScenarioSpec scenario, RunNotifier notif LOGGER.info("\n-------------------------- BDD: Scenario:{} -------------------------\n", scenario.getScenarioName()); - reportBuilder = ZeroCodeReportBuilder.newInstance().timeStamp(LocalDateTime.now()); + reportBuilder = ZeroCodeExecResultIoWriteBuilder.newInstance().timeStamp(LocalDateTime.now()); ScenarioExecutionState scenarioExecutionState = new ScenarioExecutionState(); diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java index 2e44271cf..0d860c6ef 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/ZeroCodeUnitRunner.java @@ -4,12 +4,11 @@ import com.google.inject.Injector; import com.google.inject.util.Modules; import org.jsmart.zerocode.core.di.main.ApplicationMainModule; -import org.jsmart.zerocode.core.di.module.PropertiesInjectorModule; import org.jsmart.zerocode.core.di.module.RuntimeHttpClientModule; import org.jsmart.zerocode.core.di.module.RuntimeKafkaClientModule; import org.jsmart.zerocode.core.domain.*; import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultBuilder; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeReportBuilder; +import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultIoWriteBuilder; import org.jsmart.zerocode.core.engine.listener.ZeroCodeTestReportListener; import org.jsmart.zerocode.core.httpclient.BasicHttpClient; import org.jsmart.zerocode.core.httpclient.ssl.SslTrustHttpClient; @@ -285,7 +284,7 @@ private void buildReportAndPrintToFile(Description description) { ZeroCodeExecResultBuilder reportResultBuilder = newInstance().loop(0).scenarioName(description.getClassName()); reportResultBuilder.step(logCorrelationshipPrinter.buildReportSingleStep()); - ZeroCodeReportBuilder reportBuilder = ZeroCodeReportBuilder.newInstance().timeStamp(LocalDateTime.now()); + ZeroCodeExecResultIoWriteBuilder reportBuilder = ZeroCodeExecResultIoWriteBuilder.newInstance().timeStamp(LocalDateTime.now()); reportBuilder.result(reportResultBuilder.build()); reportBuilder.printToFile(description.getClassName() + logCorrelationshipPrinter.getCorrelationId() + ".json"); } diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/LoadProcessor.java b/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/LoadProcessor.java index d42d36938..7bcd5eaba 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/LoadProcessor.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/LoadProcessor.java @@ -1,15 +1,23 @@ package org.jsmart.zerocode.core.runner.parallel; +import java.util.concurrent.atomic.AtomicInteger; +import org.jsmart.zerocode.core.engine.listener.ZeroCodeTestReportJupiterListener; import org.jsmart.zerocode.parallel.ExecutorServiceRunner; +import org.junit.platform.launcher.Launcher; +import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.TestIdentifier; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; +import org.junit.platform.launcher.core.LauncherFactory; +import org.junit.platform.launcher.listeners.SummaryGeneratingListener; +import org.junit.platform.launcher.listeners.TestExecutionSummary; import org.junit.runner.JUnitCore; import org.junit.runner.Request; import org.junit.runner.Result; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.atomic.AtomicInteger; - import static java.time.LocalDateTime.now; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; public class LoadProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(LoadProcessor.class); @@ -35,23 +43,100 @@ public LoadProcessor addTest(Class testClass, String testMethod) { return this; } + public LoadProcessor addJupiterTest(Class testClass, String testMethod) { + + Runnable zeroCodeJunitTest = createJupiterRunnable(testClass, testMethod); + + executorServiceRunner.addRunnable(zeroCodeJunitTest); + + return this; + } + public boolean process() { executorServiceRunner.runRunnables(); LOGGER.info( - "\n------------------------------------" - + "\n >> Total load test count:" + (failedCounter.get() + passedCounter.get()) - + "\n >> Passed count:" + passedCounter.get() - + "\n >> Failed count:" + failedCounter.get() - + "\n------------------------------------"); + "\n------------------------------------" + + "\n >> Total load test count:" + (failedCounter.get() + passedCounter.get()) + + "\n >> Passed count:" + passedCounter.get() + + "\n >> Failed count:" + failedCounter.get() + + "\n------------------------------------"); + + if (failedCounter.get() > 0) { + return failed; + } + + return passed; + } + + public boolean processMultiLoad() { + executorServiceRunner.runRunnablesMulti(); + + LOGGER.info( + "\n------------------------------------" + + "\n >> Total load test count:" + (failedCounter.get() + passedCounter.get()) + + "\n >> Passed count:" + passedCounter.get() + + "\n >> Failed count:" + failedCounter.get() + + "\n------------------------------------"); - if(failedCounter.get() > 0){ + if (failedCounter.get() > 0) { return failed; } return passed; } + private Runnable createJupiterRunnable(Class testClass, String testMethod) { + return () -> { + + LOGGER.info(Thread.currentThread().getName() + "\n - Parallel Junit5 test- *Start-Time = " + now()); + + final LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request() + .selectors(selectMethod(testClass, testMethod)) + .build(); + final Launcher launcher = LauncherFactory.create(); + + // ------------------------- + // Register Report listener + // ------------------------- + registerReportListener(testClass, testMethod, launcher); + + // ------------------------------ + // Register Test-Summary listener + // ------------------------------ + final SummaryGeneratingListener summaryListener = new SummaryGeneratingListener(); + launcher.registerTestExecutionListeners(summaryListener); + + launcher.execute(request); + LOGGER.info(Thread.currentThread().getName() + "\n - Parallel Junit5 test- *End-Time = " + now()); + + updatePassFailCount(summaryListener); + + }; + } + + private void updatePassFailCount(SummaryGeneratingListener summaryListener) { + TestExecutionSummary summary = summaryListener.getSummary(); + if (summary.getTotalFailureCount() > 0) { + failedCounter.incrementAndGet(); + summary.getFailures().forEach(thisFailure -> { + TestIdentifier testIdentifier = thisFailure.getTestIdentifier(); + String exceptionMessage = thisFailure.getException().getMessage(); + LOGGER.info("\n----------------------------------------------------------------------\n"); + LOGGER.info("\n###JUnit5: Test Failed Due To --> {}, \ntestIdentifier={}", exceptionMessage, testIdentifier); + LOGGER.info("\n----------------------------------------------------------------------\n"); + }); + } else { + passedCounter.incrementAndGet(); + } + } + + private void registerReportListener(Class testClass, String testMethod, Launcher launcher) { + ZeroCodeTestReportJupiterListener reportListener = + new ZeroCodeTestReportJupiterListener(testClass, testMethod ); + launcher.registerTestExecutionListeners(reportListener); + } + private Runnable createRunnable(Class testClass, String testMathod) { return () -> { LOGGER.info(Thread.currentThread().getName() + " Parallel Junit test- *Start. Time = " + now()); @@ -68,20 +153,4 @@ private Runnable createRunnable(Class testClass, String testMathod) { }; } - public boolean processMultiLoad() { - executorServiceRunner.runRunnablesMulti(); - - LOGGER.info( - "\n------------------------------------" - + "\n >> Total load test count:" + (failedCounter.get() + passedCounter.get()) - + "\n >> Passed count:" + passedCounter.get() - + "\n >> Failed count:" + failedCounter.get() - + "\n------------------------------------"); - - if(failedCounter.get() > 0){ - return failed; - } - - return passed; - } } diff --git a/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/ZeroCodeLoadRunner.java b/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/ZeroCodeLoadRunner.java index 78be61699..7981fa980 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/ZeroCodeLoadRunner.java +++ b/core/src/main/java/org/jsmart/zerocode/core/runner/parallel/ZeroCodeLoadRunner.java @@ -1,5 +1,7 @@ package org.jsmart.zerocode.core.runner.parallel; +import java.util.Arrays; +import java.util.List; import org.jsmart.zerocode.core.domain.LoadWith; import org.jsmart.zerocode.core.domain.TestMapping; import org.junit.runner.Description; @@ -10,9 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; -import java.util.List; - +import static org.jsmart.zerocode.core.utils.RunnerUtils.validateTestMethod; import static org.junit.runner.Description.createTestDescription; public class ZeroCodeLoadRunner extends ParentRunner { @@ -34,7 +34,7 @@ public ZeroCodeLoadRunner(Class testClass) throws InitializationError { @Override protected List getChildren() { validateAnnotationPresence(); - validateTestMethod(); + validateTestMethod(testClass); return Arrays.asList(testClass.getAnnotationsByType(TestMapping.class)); } @@ -91,16 +91,4 @@ private void validateAnnotationPresence() { } - private void validateTestMethod() { - String errMessage = " was invalid, please re-check and pick the correct test method to load."; - try { - TestMapping methodMapping = testClass.getAnnotation(TestMapping.class); - errMessage = "Mapped test method `" + methodMapping.testMethod() + "`" + errMessage; - methodMapping.testClass().getMethod(methodMapping.testMethod()); - } catch (NoSuchMethodException e) { - LOGGER.error(errMessage); - throw new RuntimeException(errMessage + e); - } - } - } diff --git a/core/src/main/java/org/jsmart/zerocode/core/utils/RunnerUtils.java b/core/src/main/java/org/jsmart/zerocode/core/utils/RunnerUtils.java index f64656dd6..2c679ef95 100644 --- a/core/src/main/java/org/jsmart/zerocode/core/utils/RunnerUtils.java +++ b/core/src/main/java/org/jsmart/zerocode/core/utils/RunnerUtils.java @@ -2,6 +2,7 @@ import org.apache.commons.lang.StringUtils; import org.jsmart.zerocode.core.domain.EnvProperty; +import org.jsmart.zerocode.core.domain.TestMapping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -86,4 +87,15 @@ public static String getFullyQualifiedUrl(String serviceEndPoint, } } + public static void validateTestMethod(Class testClass) { + String errMessage = " was invalid, please re-check and pick the correct test method to load."; + try { + TestMapping methodMapping = testClass.getAnnotation(TestMapping.class); + errMessage = "Mapped test method `" + methodMapping.testMethod() + "`" + errMessage; + methodMapping.testClass().getMethod(methodMapping.testMethod()); + } catch (NoSuchMethodException e) { + LOGGER.error(errMessage); + throw new RuntimeException(errMessage + e); + } + } } diff --git a/core/src/main/java/org/jsmart/zerocode/jupiter/ZeroCodeJupiterLoad.java b/core/src/main/java/org/jsmart/zerocode/jupiter/ZeroCodeJupiterLoad.java new file mode 100644 index 000000000..a1862d436 --- /dev/null +++ b/core/src/main/java/org/jsmart/zerocode/jupiter/ZeroCodeJupiterLoad.java @@ -0,0 +1,102 @@ +package org.jsmart.zerocode.jupiter; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Method; +import java.util.Arrays; +import org.apiguardian.api.API; +import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; +import org.jsmart.zerocode.core.domain.LoadWith; +import org.jsmart.zerocode.core.domain.TestMapping; +import org.jsmart.zerocode.core.report.ZeroCodeReportGenerator; +import org.jsmart.zerocode.core.report.ZeroCodeReportGeneratorImpl; +import org.jsmart.zerocode.core.runner.parallel.LoadProcessor; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.lang.String.format; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * This JUnit5 extension helps to generate load declaratively for performance testing. We can + * simply cherry-pick existing/new JUnit5 tests and run them in parallel as configured by the + * load-properties. + *

+ * This class implements BeforeEachCallback(not BeforeAllCallback), because the load generation + * can be done for each test method. This way we don't need to create multiple load generation + * classes and add them into a Test-Suite runner. Instead, just create multiple test-methods with + * annotating with @Test(from Jupiter package) and @TestMappings(...). + *

+ * Visit the Wiki page and HelloWorld repo on this for precise examples. + */ +@API( + status = EXPERIMENTAL +) +public class ZeroCodeJupiterLoad implements BeforeEachCallback { + private static final Logger LOGGER = LoggerFactory.getLogger(ZeroCodeJupiterLoad.class); + private final ObjectMapper mapper = new ObjectMapperProvider().get(); + private final ZeroCodeReportGenerator reportGenerator = new ZeroCodeReportGeneratorImpl(mapper); + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + Method testMethod = extensionContext.getRequiredTestMethod(); + Class testClass = extensionContext.getRequiredTestClass(); + String loadPropertiesFile = validateAndGetLoadPropertiesFile(testClass, testMethod); + LoadProcessor loadProcessor = new LoadProcessor(loadPropertiesFile); + + //------------------------------------------- + // On/Off Extent-Report switch + //------------------------------------------- + // Load the key 'chart.dashboard.generation' + // from 'loadPropertiesFile' + //------------------------------------------- + boolean chartAndDashBoardGeneration = false; + + + TestMapping[] testMappingArray = testMethod.getAnnotationsByType(TestMapping.class); + + Arrays.stream(testMappingArray).forEach(thisMapping -> { + loadProcessor.addJupiterTest(thisMapping.testClass(), thisMapping.testMethod()); + }); + + boolean hasFailed = loadProcessor.processMultiLoad(); + + reportGenerator.generateCsvReport(); + if (chartAndDashBoardGeneration) { + reportGenerator.generateExtentReport(); + } + + if (hasFailed) { + String failureMessage = testClass.getName() + " with load/stress test(s): " + testMethod + " have Failed"; + LOGGER.error("\n" + failureMessage + ". \nSee the 'target/logs' for individual failures " + + "\n-Also- \nSee the 'target/' for granular 'csv report' for pass/fail/response-delay statistics.\uD83D\uDE0E"); + String testDescription = testClass + "#" + testMethod; + + fail(testDescription, new RuntimeException(failureMessage)); + } else { + LOGGER.info("\nAll Passed \uD83D\uDC3C. \nSee the granular 'csv report' for individual test statistics."); + } + + } + + private String validateAndGetLoadPropertiesFile(Class testClass, Method method) { + LoadWith loadClassWith = testClass.getAnnotation(LoadWith.class); + LoadWith loadMethodWith = method.getAnnotation(LoadWith.class); + if (loadClassWith != null) { + return loadClassWith.value(); + } + + if (loadMethodWith != null) { + return loadMethodWith.value(); + } + + throw new RuntimeException( + format("\n<< Ah! You missed to put the @LoadWith(...) on the Class '%s' or Method '%s' >> ", + testClass.getName(), method.getName()) + ); + + } + +} diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilderTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilderTest.java similarity index 85% rename from core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilderTest.java rename to core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilderTest.java index 1289ce08a..2c4a6cf5b 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeReportBuilderTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/domain/builders/ZeroCodeExecResultIoWriteBuilderTest.java @@ -2,7 +2,7 @@ import org.junit.Test; -public class ZeroCodeReportBuilderTest { +public class ZeroCodeExecResultIoWriteBuilderTest { @Test public void testActual() throws Exception { diff --git a/core/src/test/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportTest.java b/core/src/test/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportTest.java index 2f8eb957f..4517529c1 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/domain/reports/ZeroCodeReportTest.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; -import org.jsmart.zerocode.core.domain.builders.ZeroCodeReportBuilder; +import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultIoWriteBuilder; import org.jsmart.zerocode.core.domain.builders.ZeroCodeReportStepBuilder; import org.jsmart.zerocode.core.domain.builders.ZeroCodeExecResultBuilder; import org.jsmart.zerocode.core.utils.SmartUtils; @@ -32,7 +32,7 @@ public class ZeroCodeReportTest { @Test public void willSerialize_ToJson() throws Exception { - ZeroCodeReport javaBuilt = ZeroCodeReportBuilder.newInstance() + ZeroCodeReport javaBuilt = ZeroCodeExecResultIoWriteBuilder.newInstance() .timeStamp(LocalDateTime.now()) .results(Arrays.asList(ZeroCodeExecResultBuilder.newInstance() .scenarioName("scenario name") diff --git a/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java b/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java index 5d84b4119..b05c464fc 100644 --- a/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java +++ b/core/src/test/java/org/jsmart/zerocode/core/report/ZeroCodeReportGeneratorImplTest.java @@ -1,5 +1,7 @@ package org.jsmart.zerocode.core.report; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.jsmart.zerocode.core.di.provider.ObjectMapperProvider; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -17,11 +19,12 @@ public class ZeroCodeReportGeneratorImplTest { private ZeroCodeReportGeneratorImpl zeroCodeReportGenerator; + ObjectMapper mapper = new ObjectMapperProvider().get(); @Before public void setItUp() throws Exception { - zeroCodeReportGenerator = new ZeroCodeReportGeneratorImpl(); + zeroCodeReportGenerator = new ZeroCodeReportGeneratorImpl(mapper); } diff --git a/junit5-testing/pom.xml b/junit5-testing/pom.xml new file mode 100644 index 000000000..4a69f8de1 --- /dev/null +++ b/junit5-testing/pom.xml @@ -0,0 +1,88 @@ + + + 4.0.0 + + zerocode-tdd-parent + org.jsmart + 1.3.6-SNAPSHOT + + + org.jsmart + junit5-testing + 1.3.6-SNAPSHOT + + jar + Zerocode JUnit5 Jupiter Testing + Zerocode tests with JUnit5 Jupiter Engine + + + 1.8 + 1.1.8 + + + + + zerocode-tdd + org.jsmart + ${project.version} + + + org.junit.jupiter + junit-jupiter-params + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.vintage + junit-vintage-engine + + + org.junit.platform + junit-platform-runner + + + + org.jsmart + micro-simulator + ${micro-simulator.version} + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + + + + + + + + + + org.jsmart.zerocode.tests.load.jupiter.JUnit5LoadTest + + + + + + \ No newline at end of file diff --git a/junit5-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/CustomHttpClient.java b/junit5-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/CustomHttpClient.java new file mode 100644 index 000000000..e4b29b5dd --- /dev/null +++ b/junit5-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/httpclient/CustomHttpClient.java @@ -0,0 +1,11 @@ +package org.jsmart.zerocode.zerocodejavaexec.httpclient; + +import org.jsmart.zerocode.core.httpclient.BasicHttpClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CustomHttpClient extends BasicHttpClient { + private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpClient.class); + //TODO - With security headers +} + diff --git a/junit5-testing/src/main/resources/logback.xml b/junit5-testing/src/main/resources/logback.xml new file mode 100644 index 000000000..f5bc0aef0 --- /dev/null +++ b/junit5-testing/src/main/resources/logback.xml @@ -0,0 +1,25 @@ + + + + target/logs/your_app_tests_logs.log + true + + %d [%thread] %-5level %logger{100} - %msg%n + + + + + + + + %d [%thread] %-5level %logger{100} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/stubserver/RunMeFirstLocalMockRESTServer.java b/junit5-testing/src/test/java/org/jsmart/zerocode/stubserver/RunMeFirstLocalMockRESTServer.java new file mode 100644 index 000000000..14e64fadc --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/stubserver/RunMeFirstLocalMockRESTServer.java @@ -0,0 +1,34 @@ +package org.jsmart.zerocode.stubserver; + +import org.jsmart.simulator.annotations.ApiRepo; +import org.jsmart.simulator.impl.JsonBasedSimulator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/* + * Created by Siddha on 27/04/2015. + * + * Are you done with the web server ? To stop this REST server, simply press Ctrl+c or Stop button on your IDE + * + */ +@ApiRepo("localhost_stubs") +public class RunMeFirstLocalMockRESTServer extends JsonBasedSimulator { + private static final Logger logger = LoggerFactory.getLogger(RunMeFirstLocalMockRESTServer.class); + + public static final int PORT = 9999; + + public RunMeFirstLocalMockRESTServer(int port) { + super(port); + } + + public static void main(String[] args) { + logger.info("\n### REST Helper web-service starting..."); + + new RunMeFirstLocalMockRESTServer(PORT).start(); + + logger.info("\n### REST Helper web-service started."); + + System.out.println("\n------ Done? To stop this REST server, simply press Ctrl+c or Stop button on your IDE -------"); + + } +} diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/GitHubHelloWorldTest.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/GitHubHelloWorldTest.java new file mode 100644 index 000000000..fa02f9671 --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/GitHubHelloWorldTest.java @@ -0,0 +1,18 @@ +package org.jsmart.zerocode.tests.junit4; + +import org.jsmart.zerocode.core.domain.JsonTestCase; +import org.jsmart.zerocode.core.domain.TargetEnv; +import org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner; +import org.junit.Test; +import org.junit.runner.RunWith; + +@TargetEnv("github_host.properties") +@RunWith(ZeroCodeUnitRunner.class) +public class GitHubHelloWorldTest { + + @Test + @JsonTestCase("helloworld_github_REST_api/GitHub_REST_api_sample_assertions.json") + public void testGitGubSample_RESTApi() throws Exception { + } + +} diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/JUnit4Test.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/JUnit4Test.java new file mode 100644 index 000000000..43fc69491 --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/junit4/JUnit4Test.java @@ -0,0 +1,17 @@ +package org.jsmart.zerocode.tests.junit4; + + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + + +public class JUnit4Test { + + @Test + public void testJunit4_passed() { + String msg = "junit4 works as usual"; + assertTrue("junit4 works as usual".equals(msg)); + } + +} \ No newline at end of file diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/jupiter/JUnit5Test.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/jupiter/JUnit5Test.java new file mode 100644 index 000000000..b9a651f9a --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/jupiter/JUnit5Test.java @@ -0,0 +1,26 @@ +package org.jsmart.zerocode.tests.jupiter; + +import org.jsmart.zerocode.tests.postgres.ExtensionA; +import org.jsmart.zerocode.tests.postgres.ExtensionB; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import static java.lang.System.out; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@ExtendWith({ExtensionA.class, ExtensionB.class}) +public class JUnit5Test { + + @Test + public void testX() { + out.println("JUnit5 ---> testX()"); + assertTrue(2 == 3); + } + + @Test + public void testY() { + out.println("JUnit5 ---> testY()"); + assertTrue(2 == 2); + } + +} \ No newline at end of file diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/loadjupiter/JUnit5LoadTest.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/loadjupiter/JUnit5LoadTest.java new file mode 100644 index 000000000..633cd03d5 --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/loadjupiter/JUnit5LoadTest.java @@ -0,0 +1,26 @@ +package org.jsmart.zerocode.tests.loadjupiter; + +import org.jsmart.zerocode.core.domain.LoadWith; +import org.jsmart.zerocode.core.domain.TestMapping; +import org.jsmart.zerocode.core.domain.TestMappings; +import org.jsmart.zerocode.jupiter.ZeroCodeJupiterLoad; +import org.jsmart.zerocode.tests.jupiter.JUnit5Test; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith({ZeroCodeJupiterLoad.class}) +public class JUnit5LoadTest { + + @Test + @LoadWith("load_generation.properties") + @TestMappings({ + @TestMapping(testClass = JUnit5Test.class, testMethod = "testX"), + @TestMapping(testClass = JUnit5Test.class, testMethod = "testY") + }) + public void testLoad() { + // -------------------- + // No code needed here + // -------------------- + } + +} \ No newline at end of file diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionA.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionA.java new file mode 100644 index 000000000..7adbef1bb --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionA.java @@ -0,0 +1,33 @@ +package org.jsmart.zerocode.tests.postgres; + +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class ExtensionA implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { + + @Override + public void afterEach(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionA - afterEach"); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionA - beforeEach"); + + } + + @Override + public void afterAll(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionA - afterAll"); + + } + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionA - beforeAll"); + + } +} diff --git a/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionB.java b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionB.java new file mode 100644 index 000000000..3f7f4cb57 --- /dev/null +++ b/junit5-testing/src/test/java/org/jsmart/zerocode/tests/postgres/ExtensionB.java @@ -0,0 +1,34 @@ +package org.jsmart.zerocode.tests.postgres; + + +import org.junit.jupiter.api.extension.AfterAllCallback; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +public class ExtensionB implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback { + + @Override + public void afterEach(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionB - afterEach"); + } + + @Override + public void beforeEach(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionB - beforeEach"); + + } + + @Override + public void afterAll(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionB - afterAll"); + + } + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + System.out.println("ExtentionB - beforeAll"); + + } +} diff --git a/junit5-testing/src/test/resources/github_host.properties b/junit5-testing/src/test/resources/github_host.properties new file mode 100644 index 000000000..1fe6afa84 --- /dev/null +++ b/junit5-testing/src/test/resources/github_host.properties @@ -0,0 +1,6 @@ +# Web Server host and port +web.application.endpoint.host=https://api.github.com +# Web Service Port; Leave it blank in case it is default port i.e. 80 or 443 etc +web.application.endpoint.port= +# Web Service context; Leave it blank in case you do not have a common context +web.application.endpoint.context= diff --git a/junit5-testing/src/test/resources/helloworld_github_REST_api/GitHub_REST_api_sample_assertions.json b/junit5-testing/src/test/resources/helloworld_github_REST_api/GitHub_REST_api_sample_assertions.json new file mode 100644 index 000000000..b9a785c67 --- /dev/null +++ b/junit5-testing/src/test/resources/helloworld_github_REST_api/GitHub_REST_api_sample_assertions.json @@ -0,0 +1,18 @@ +{ + "scenarioName": "GitHub Version-Details REST API will GET, version and server details @@Emma", + "steps": [ + { + "name": "get_github_server_details", + "url": "/users/octocat/orgs", + "operation": "GET", + "request": { + "headers":{ + "api_key": "efg-135-xyz-9393" + } + }, + "assertions": { + "status": 200 + } + } + ] +} diff --git a/junit5-testing/src/test/resources/load_generation.properties b/junit5-testing/src/test/resources/load_generation.properties new file mode 100755 index 000000000..43a2edf4c --- /dev/null +++ b/junit5-testing/src/test/resources/load_generation.properties @@ -0,0 +1,22 @@ +# You can enter as many threads to stimulate a load test. A single user is represented by each Thread. So if you wish +# to simulate a load test with 5 concurrent users then you need to enter 5 as the value for this property. A high end +# machine will be able to spawn more number of threads. To keep the consistent(or nearly consistent) gap between the +# threads, adjust this number with 'ramp.up.period.in.seconds' and the actual response time of the API end point. +# For "@RunWith(ZeroCodeMultiLoadRunner.class)", set this to at least equal to number of "@TestMapping" or more, +# otherwise there wont be enough threads to run each test. +number.of.threads=2 + +# It indicates the time taken to create all of the threads needed to fork the requests. If you set 10 seconds as the +# ramp-up period for 5 threads then the framework will take 10 seconds to create those 5 threads, i.e. each thread +# will be at work appx 2 secs gap between the requests. Also by setting its value to 0 all the threads can be created +# at once at the same time. Note- If you want to fire more threads/user-requests in less ramp up time e.g. 5 threads +# in 2secs(or 5 threads in 1 sec), then, use '@UseHttpClient(SslTrustHttpClient.class)' as this 'client' closes the +# connection before making the next connection. +ramp.up.period.in.seconds=4 + +# By specifying its value framework gets to know that how many times the test(s), i.e. the number of requests will be +# repeated per every 'ramp.up.period.in.seconds'. +# Supposing number.of.threads = x, ramp.up.period.in.seconds = y, loop.count = i +# then (x * i) = number of requests will be fired over (y * i) seconds. If x=5, i=3, y=20, then 15 requests will be +# fired in 60 seconds which means- every request in 4 seconds gap. 60/15 or 20/5 = 4seconds. +loop.count=1 diff --git a/junit5-testing/src/test/resources/loadtesting/github_get_api_test_case.json b/junit5-testing/src/test/resources/loadtesting/github_get_api_test_case.json new file mode 100644 index 000000000..b10f695c9 --- /dev/null +++ b/junit5-testing/src/test/resources/loadtesting/github_get_api_test_case.json @@ -0,0 +1,23 @@ +{ + "scenarioName": "Load testing- Git Hub GET API", + "steps": [ + { + "name": "get_user_details", + "url": "/users/octocat", + "operation": "GET", + "request": { + }, + "assertions": { + "status": 200, + "body": { + "login" : "octocat", + "id" : 583231, + "avatar_url" : "https://avatars3.githubusercontent.com/u/583231?v=4", + "type" : "User", + "name" : "The Octocat", + "company" : "GitHub" + } + } + } + ] +} diff --git a/junit5-testing/src/test/resources/localhost_stubs/localhost_REST_fake_end_points_stubs.json b/junit5-testing/src/test/resources/localhost_stubs/localhost_REST_fake_end_points_stubs.json new file mode 100644 index 000000000..6113f5402 --- /dev/null +++ b/junit5-testing/src/test/resources/localhost_stubs/localhost_REST_fake_end_points_stubs.json @@ -0,0 +1,226 @@ +{ + "name": "Localhost mocked aka stubbed aka fake REST Endpoints - GET POST PUT apis", + "apis": [ + { + "name": "Sample_POST_Employee_Create", + "operation": "POST", + "url": "/api/v1/google-uk/employees", + "ignoreBody": true, + "response": { + "status": 201, + "body": { + "id": 1000, + "name": "Larry Pg", + "addresses": [ + { + "gpsLocation": "x9000-y9000z-9000-home" + }, + { + "gpsLocation": "x9000-y9000z-9000-home-off" + } + ] + } + } + }, + { + "name": "sample POST with matching body", + "operation": "POST", + "url": "/api/v1/employees", + "ignoreBody": false, + "body": { + "name": "Emma", + "surName": "Norton" + }, + "response": { + "status": 201, + "body": { + "id": 39001, + "ldapId": "emmanorton" + } + } + }, + { + "name": "sample GET for Emma Norton", + "operation": "GET", + "url": "/api/v1/employees/39001", + "response": { + "status": 200, + "body": { + "id": 39001, + "ldapId": "emmanorton", + "name": "Emma", + "surName": "Norton" + } + } + }, + { + "name": "Sample_Get_Employee_by_Id", + "operation": "GET", + "url": "/api/v1/google-uk/employees/999", + "response": { + "status": 200, + "body": { + "id": 999, + "name": "Larry P", + "addresses": [ + { + "gpsLocation": "x1000-25000-z30000" + }, + { + "gpsLocation": "x3000-y5000-z70000" + } + ] + } + } + }, + { + "name": "Screening - sample POST with matching body", + "operation": "POST", + "url": "/api/v1/employees/screening", + "ignoreBody": false, + "body": { + "empId": "EMP39001", + "originAddress": { + "addressId":"lon-hsbc-5432", + "countryOfOrigin":"UK" + } + }, + "response": { + "status": 201, + "body": { + "id": "SCRUNIQUEID5003" + } + } + }, + { + "name": "Screening - sample GET", + "operation": "GET", + "url": "/api/v1/employees/screening/SCRUNIQUEID5003", + "response": { + "status": 200, + "body": { + "id": "SCRUNIQUEID5003", + "empId": "EMP39001", + "originAddress": { + "addressId":"lon-hsbc-5432", + "countryOfOrigin":"UK" + } + } + } + }, + { + "name": "Sample_Get_Created_Employee_by_Id", + "operation": "GET", + "url": "/api/v1/google-uk/employees/1000", + "response": { + "status": 200, + "body": { + "id": 1000, + "name": "Larry Pg", + "addresses": [ + { + "gpsLocation": "x9000-y9000z-9000-home" + }, + { + "gpsLocation": "x9000-y9000z-9000-home-off" + } + ] + } + } + }, + { + "name": "sample_get_api", + "operation": "GET", + "url": "/api/v1/google-uk/employees/UK1001", + "response": { + "status": 200, + "body": { + "id": "UK1001", + "name": "Bobby Lion", + "addresses": [ + { + "line1": "HOME, London, PostCode - IG1 5TX" + }, + { + "line1": "OFFICE, Newark, ZIP-730290" + } + ] + } + } + }, + { + "name": "bare_string_get", + "operation": "GET", + "url": "/api/v1/google-uk/employees/101", + "response": { + "status": 200, + "body": "I am emp No 101. Nothing more than this I can respond" + } + }, + { + "name": "Sample_Get_Full_Employee_by_Id", + "operation": "GET", + "url": "/api/v1/employees/emp1001", + "response": { + "status": 200, + "body": { + "id": "emp1001", + "name": "Jeff Bezos", + "achievements": "Amazon", + "empType": "Self Employed", + "addresses": [ + { + "type": "Office", + "line1": "39 NewYork Street", + "zip": "560 390" + }, + { + "type": "Home", + "line1": "99 Piscataway", + "zip": "560 001" + } + ] + } + } + }, + { + "name": "Sample_Get_Address_by_emp_id", + "operation": "GET", + "url": "/api/v1/addresses/empoyee/emp1001", + "response": { + "status": 200, + "body": { + "empId": "emp1001", + "addresses": [ + { + "addressId": "addr-001", + "type": "Office", + "line1": "39 NewYork Street", + "zip": "560 390" + }, + { + "addressId": "addr-002", + "type": "Home", + "line1": "99 Piscataway", + "zip": "560 001" + } + ] + } + } + }, + { + "name": "Mock GET employee details including DOB", + "operation": "GET", + "url": "/api/v1/google-uk/employees/UK-LON-1002", + "response": { + "status": 200, + "body": { + "empId": "UK-LON-1002", + "city": "UK-London", + "dob": "1989-07-09" + } + } + } + + ] +} \ No newline at end of file diff --git a/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java b/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java new file mode 100644 index 000000000..860646189 --- /dev/null +++ b/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/ExampleUtils.java @@ -0,0 +1,5 @@ +package org.jsmart.zerocode.zerocodejavaexec.utils; + +public class ExampleUtils { + +} diff --git a/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/TokenGenerator.java b/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/TokenGenerator.java deleted file mode 100644 index dd693df1e..000000000 --- a/kafka-testing/src/main/java/org/jsmart/zerocode/zerocodejavaexec/utils/TokenGenerator.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.jsmart.zerocode.zerocodejavaexec.utils; - -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Map; - -public class TokenGenerator { - - public Map generateNew(String anyParam){ - Map tokenMap = new HashMap<>(); - - // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // Your token generation logic goes here. - // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - // You need to put a valid implementation for this token. - // For time being it's unique here as current time-stamp. - // The key "token" here is just for demo purpose. - // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - String uniqueToken = tokenFromCurrentTimeStamp(); - - // ------------------------------------ - // Now put this token into a map key - // - Choose any key name e.g. newToken - // ------------------------------------ - tokenMap.put("newToken", uniqueToken); - - return tokenMap; - } - - private String tokenFromCurrentTimeStamp() { - return LocalDateTime.now().toString() - .replace(":", "-") - .replace(".", "-"); - } -} diff --git a/pom.xml b/pom.xml index 2c1c85b15..4e977be43 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,7 @@ core http-testing kafka-testing + junit5-testing @@ -58,6 +59,9 @@ + 5.4.2 + 5.4.2 + 1.4.2 4.12 2.9.7 23.0 @@ -79,7 +83,7 @@ 4.0.9 2.1.0 2.6.2 - + 3.2 1.8 1.8 @@ -90,6 +94,26 @@ + + org.junit.jupiter + junit-jupiter-params + ${junit5.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit5.version} + + + org.junit.vintage + junit-vintage-engine + ${junit.vintage.version} + + + org.junit.platform + junit-platform-runner + ${junit-platform-runner.version} + com.google.code.gson gson