From ae2d9e4c5875a5166c507fb0c24f5f42db19a236 Mon Sep 17 00:00:00 2001 From: Peter Thomas Date: Tue, 20 Aug 2019 15:58:13 -0700 Subject: [PATCH] unified cli for karate core somewhat #827 in the future, the netty picocli has to be merged and we also would have native html parallel reports but for now, we can start testing the vs code plugin for this parallel execution will now generate native html report and continuously update the results-json.txt which the plugin can read and update etc --- karate-core/README.md | 17 ++-- .../main/java/com/intuit/karate/Runner.java | 23 ++++- .../java/com/intuit/karate/RunnerOptions.java | 7 ++ .../intuit/karate/cli/CliExecutionHook.java | 89 +++++++++++++++++++ .../karate/{IdeUtils.java => cli/Main.java} | 49 +++++++--- .../java/com/intuit/karate/core/Engine.java | 2 +- .../intuit/karate/core/ExecutionContext.java | 11 ++- .../com/intuit/karate/core/FeatureResult.java | 9 +- .../intuit/karate/driver/DevToolsDriver.java | 2 +- .../java/com/intuit/karate/driver/Driver.java | 6 +- .../com/intuit/karate/driver/WebDriver.java | 2 +- .../src/main/java/cucumber/api/cli/Main.java | 4 +- .../java/com/intuit/karate/IdeUtilsTest.java | 9 +- .../karate/cli/CliExecutionHookTest.java | 16 ++++ .../src/test/java/demo/hooks/hooks.feature | 3 +- .../src/test/java/driver/core/test-01.feature | 2 +- .../com/intuit/karate/junit4/FeatureInfo.java | 2 +- .../com/intuit/karate/junit5/FeatureNode.java | 2 +- karate-netty/README.md | 7 ++ .../src/main/java/com/intuit/karate/Main.java | 13 ++- .../java/com/intuit/karate/ui/AppSession.java | 2 +- 21 files changed, 227 insertions(+), 50 deletions(-) create mode 100644 karate-core/src/main/java/com/intuit/karate/cli/CliExecutionHook.java rename karate-core/src/main/java/com/intuit/karate/{IdeUtils.java => cli/Main.java} (85%) create mode 100644 karate-core/src/test/java/com/intuit/karate/cli/CliExecutionHookTest.java diff --git a/karate-core/README.md b/karate-core/README.md index f51183737..690eb7850 100644 --- a/karate-core/README.md +++ b/karate-core/README.md @@ -131,7 +131,7 @@ Cookies cookie() - | driver.cookie + cookie(set) | driver.cookies | deleteCookie() | clearCookies() @@ -1091,17 +1091,20 @@ Normal page reload, does *not* clear cache. ## `fullscreen()` -## `driver.cookie` -Set a cookie: +## `cookie(set)` +Set a cookie. The method argument is JSON, so that you can pass more data in addition to the `value` such as `domain` and `url`. Most servers expect the `domain` to be set correctly like this: ```cucumber -Given def cookie2 = { name: 'hello', value: 'world' } -When driver.cookie = cookie2 -Then match driver.cookies contains '#(^cookie2)' +Given def myCookie = { name: 'hello', value: 'world', domain: '.mycompany.com' } +When cookie(myCookie) +Then match driver.cookies contains '#(^myCookie)' ``` +> Note that you can do the above as a one-liner like this: `* cookie({ name: 'hello', value: 'world' })`, just keep in mind here that then it would follow the rules of [Enclosed JavaScript](https://github.com/intuit/karate#enclosed-javascript) (not [Embedded Expressions](https://github.com/intuit/karate#embedded-expressions)) + ## `cookie()` -Get a cookie by name: +Get a cookie by name. Note how Karate's [`match`](https://github.com/intuit/karate#match) syntax comes in handy. + ```cucumber * def cookie1 = { name: 'foo', value: 'bar' } And match driver.cookies contains '#(^cookie1)' diff --git a/karate-core/src/main/java/com/intuit/karate/Runner.java b/karate-core/src/main/java/com/intuit/karate/Runner.java index 013b40343..763265b28 100644 --- a/karate-core/src/main/java/com/intuit/karate/Runner.java +++ b/karate-core/src/main/java/com/intuit/karate/Runner.java @@ -68,6 +68,16 @@ public Builder path(String... paths) { this.paths.addAll(Arrays.asList(paths)); return this; } + + public Builder path(List paths) { + this.paths.addAll(paths); + return this; + } + + public Builder tags(List tags) { + this.tags.addAll(tags); + return this; + } public Builder tags(String... tags) { this.tags.addAll(Arrays.asList(tags)); @@ -108,7 +118,7 @@ List resources() { return resources; } - Results parallel(int threadCount) { + public Results parallel(int threadCount) { this.threadCount = threadCount; return Runner.parallel(this); } @@ -118,7 +128,12 @@ Results parallel(int threadCount) { public static Builder path(String... paths) { Builder builder = new Builder(); return builder.path(paths); - } + } + + public static Builder path(List paths) { + Builder builder = new Builder(); + return builder.path(paths); + } //========================================================================== // @@ -200,7 +215,7 @@ public static Results parallel(Builder options) { feature.setCallLine(resource.getLine()); FeatureContext featureContext = new FeatureContext(null, feature, options.tagSelector()); CallContext callContext = CallContext.forAsync(feature, options.hooks, null, false); - ExecutionContext execContext = new ExecutionContext(results.getStartTime(), featureContext, callContext, reportDir, + ExecutionContext execContext = new ExecutionContext(results, results.getStartTime(), featureContext, callContext, reportDir, r -> featureExecutor.submit(r), scenarioExecutor, Thread.currentThread().getContextClassLoader()); featureResults.add(execContext.result); FeatureExecutionUnit unit = new FeatureExecutionUnit(execContext); @@ -284,7 +299,7 @@ public static void callAsync(String path, Map arg, ExecutionHook Feature feature = FileUtils.parseFeatureAndCallTag(path); FeatureContext featureContext = new FeatureContext(null, feature, null); CallContext callContext = CallContext.forAsync(feature, Collections.singletonList(hook), arg, true); - ExecutionContext executionContext = new ExecutionContext(System.currentTimeMillis(), featureContext, callContext, null, system, null); + ExecutionContext executionContext = new ExecutionContext(null, System.currentTimeMillis(), featureContext, callContext, null, system, null); FeatureExecutionUnit exec = new FeatureExecutionUnit(executionContext); exec.setNext(next); system.accept(exec); diff --git a/karate-core/src/main/java/com/intuit/karate/RunnerOptions.java b/karate-core/src/main/java/com/intuit/karate/RunnerOptions.java index d8d89eb21..cd8ef0aec 100644 --- a/karate-core/src/main/java/com/intuit/karate/RunnerOptions.java +++ b/karate-core/src/main/java/com/intuit/karate/RunnerOptions.java @@ -55,6 +55,9 @@ public class RunnerOptions { @CommandLine.Option(names = {"-t", "--tags"}, description = "tags") List tags; + + @CommandLine.Option(names = {"-T", "--threads"}, description = "threads") + int threads = 1; @CommandLine.Option(names = {"-", "--plugin"}, description = "plugin (not supported)") List plugins; @@ -81,6 +84,10 @@ public List getFeatures() { return features; } + public int getThreads() { + return threads; + } + public static RunnerOptions parseStringArgs(String[] args) { RunnerOptions options = CommandLine.populateCommand(new RunnerOptions(), args); List featuresTemp = new ArrayList(); diff --git a/karate-core/src/main/java/com/intuit/karate/cli/CliExecutionHook.java b/karate-core/src/main/java/com/intuit/karate/cli/CliExecutionHook.java new file mode 100644 index 000000000..bfb5af77b --- /dev/null +++ b/karate-core/src/main/java/com/intuit/karate/cli/CliExecutionHook.java @@ -0,0 +1,89 @@ +/* + * The MIT License + * + * Copyright 2019 Intuit Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.intuit.karate.cli; + +import com.intuit.karate.core.Engine; +import com.intuit.karate.core.ExecutionHook; +import com.intuit.karate.core.Feature; +import com.intuit.karate.core.FeatureResult; +import com.intuit.karate.core.PerfEvent; +import com.intuit.karate.core.Scenario; +import com.intuit.karate.core.ScenarioContext; +import com.intuit.karate.core.ScenarioResult; +import com.intuit.karate.http.HttpRequestBuilder; +import java.util.concurrent.locks.ReentrantLock; + +/** + * + * @author pthomas3 + */ +public class CliExecutionHook implements ExecutionHook { + + private final String targetDir; + private final boolean intellij; + private final ReentrantLock LOCK = new ReentrantLock(); + + public CliExecutionHook(String targetDir, boolean intellij) { + this.targetDir = targetDir; + this.intellij = intellij; + } + + @Override + public boolean beforeScenario(Scenario scenario, ScenarioContext context) { + return true; + } + + @Override + public void afterScenario(ScenarioResult result, ScenarioContext context) { + + } + + @Override + public boolean beforeFeature(Feature feature) { + return true; + } + + @Override + public void afterFeature(FeatureResult result) { + if (intellij) { + Main.log(result); + } + Engine.saveResultHtml(targetDir, result, null); + if (LOCK.tryLock()) { + Engine.saveStatsJson(targetDir, result.getResults(), null); + LOCK.unlock(); + } + } + + @Override + public String getPerfEventName(HttpRequestBuilder req, ScenarioContext context) { + return null; + } + + @Override + public void reportPerfEvent(PerfEvent event) { + + } + +} diff --git a/karate-core/src/main/java/com/intuit/karate/IdeUtils.java b/karate-core/src/main/java/com/intuit/karate/cli/Main.java similarity index 85% rename from karate-core/src/main/java/com/intuit/karate/IdeUtils.java rename to karate-core/src/main/java/com/intuit/karate/cli/Main.java index c08324499..fecb7b319 100644 --- a/karate-core/src/main/java/com/intuit/karate/IdeUtils.java +++ b/karate-core/src/main/java/com/intuit/karate/cli/Main.java @@ -21,8 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package com.intuit.karate; +package com.intuit.karate.cli; +import com.intuit.karate.FileUtils; +import com.intuit.karate.Resource; +import com.intuit.karate.Results; +import com.intuit.karate.Runner; +import com.intuit.karate.RunnerOptions; +import com.intuit.karate.StringUtils; import com.intuit.karate.core.Engine; import com.intuit.karate.core.Feature; import com.intuit.karate.core.FeatureParser; @@ -43,30 +49,49 @@ * * @author pthomas3 */ -public class IdeUtils { +public class Main { private static final Pattern COMMAND_NAME = Pattern.compile("--name (.+?\\$)"); - public static void exec(String[] args) { - String command = System.getProperty("sun.java.command"); + public static void main(String[] args) { + String command; + if (args.length > 0) { + command = StringUtils.join(args, ' '); + } else { + command = System.getProperty("sun.java.command"); + } System.out.println("command: " + command); boolean isIntellij = command.contains("org.jetbrains"); RunnerOptions options = RunnerOptions.parseCommandLine(command); - String name = options.getName(); - List features = options.getFeatures(); - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - List resources = FileUtils.scanForFeatureFiles(features, cl); + String targetDir = FileUtils.getBuildDir() + File.separator + "surefire-reports"; + if (options.getThreads() == 1) { + runNormal(options, targetDir, isIntellij); + } else { + runParallel(options, targetDir, isIntellij); + } + } + + private static void runNormal(RunnerOptions options, String targetDir, boolean isIntellij) { String tagSelector = Tags.fromKarateOptionsTags(options.getTags()); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + List resources = FileUtils.scanForFeatureFiles(options.getFeatures(), cl); for (Resource resource : resources) { Feature feature = FeatureParser.parse(resource); - feature.setCallName(name); + feature.setCallName(options.getName()); feature.setCallLine(resource.getLine()); FeatureResult result = Engine.executeFeatureSync(null, feature, tagSelector, null); if (isIntellij) { log(result); } - Engine.saveResultHtml(FileUtils.getBuildDir() + File.separator + "surefire-reports", result, null); - } + Engine.saveResultHtml(targetDir, result, null); + } + } + + private static void runParallel(RunnerOptions ro, String targetDir, boolean isIntellij) { + CliExecutionHook hook = new CliExecutionHook(targetDir, isIntellij); + Runner.path(ro.getFeatures()) + .tags(ro.getTags()).scenarioName(ro.getName()) + .hook(hook).parallel(ro.getThreads()); } public static StringUtils.Pair parseCommandLine(String commandLine, String cwd) { @@ -149,7 +174,7 @@ private static StringUtils.Pair details(Throwable error) { } } - private static void log(FeatureResult fr) { + public static void log(FeatureResult fr) { Feature f = fr.getFeature(); String uri = fr.getDisplayUri(); String featureName = Feature.KEYWORD + ": " + escape(f.getName()); diff --git a/karate-core/src/main/java/com/intuit/karate/core/Engine.java b/karate-core/src/main/java/com/intuit/karate/core/Engine.java index d3d07dcef..4d5664cbc 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/Engine.java +++ b/karate-core/src/main/java/com/intuit/karate/core/Engine.java @@ -104,7 +104,7 @@ public static FeatureResult executeFeatureSync(String env, Feature feature, Stri if (callContext == null) { callContext = new CallContext(null, true); } - ExecutionContext exec = new ExecutionContext(System.currentTimeMillis(), featureContext, callContext, null, null, null); + ExecutionContext exec = new ExecutionContext(null, System.currentTimeMillis(), featureContext, callContext, null, null, null); FeatureExecutionUnit unit = new FeatureExecutionUnit(exec); unit.run(); return exec.result; diff --git a/karate-core/src/main/java/com/intuit/karate/core/ExecutionContext.java b/karate-core/src/main/java/com/intuit/karate/core/ExecutionContext.java index a8c6a8b42..7b00312e3 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/ExecutionContext.java +++ b/karate-core/src/main/java/com/intuit/karate/core/ExecutionContext.java @@ -25,6 +25,7 @@ import com.intuit.karate.CallContext; import com.intuit.karate.FileUtils; +import com.intuit.karate.Results; import java.io.File; import java.util.concurrent.ExecutorService; import java.util.function.Consumer; @@ -35,6 +36,7 @@ */ public class ExecutionContext { + public final Results results; public final long startTime; public final FeatureContext featureContext; public final CallContext callContext; @@ -45,16 +47,17 @@ public class ExecutionContext { private final File reportDir; - public ExecutionContext(long startTime, FeatureContext featureContext, CallContext callContext, String reportDirString, + public ExecutionContext(Results results, long startTime, FeatureContext featureContext, CallContext callContext, String reportDirString, Consumer system, ExecutorService scenarioExecutor) { - this(startTime, featureContext, callContext, reportDirString, system, scenarioExecutor, null); + this(results, startTime, featureContext, callContext, reportDirString, system, scenarioExecutor, null); } - public ExecutionContext(long startTime, FeatureContext featureContext, CallContext callContext, String reportDirString, + public ExecutionContext(Results results, long startTime, FeatureContext featureContext, CallContext callContext, String reportDirString, Consumer system, ExecutorService scenarioExecutor, ClassLoader classLoader) { + this.results = results; this.scenarioExecutor = scenarioExecutor; this.startTime = startTime; - result = new FeatureResult(featureContext.feature); + result = new FeatureResult(results, featureContext.feature); this.featureContext = featureContext; this.callContext = callContext; this.classLoader = classLoader; diff --git a/karate-core/src/main/java/com/intuit/karate/core/FeatureResult.java b/karate-core/src/main/java/com/intuit/karate/core/FeatureResult.java index f2eeb7856..4bcc0b1fd 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/FeatureResult.java +++ b/karate-core/src/main/java/com/intuit/karate/core/FeatureResult.java @@ -25,6 +25,7 @@ import com.intuit.karate.FileUtils; import com.intuit.karate.JsonUtils; +import com.intuit.karate.Results; import com.intuit.karate.ScriptValueMap; import com.intuit.karate.StringUtils; import com.intuit.karate.exception.KarateException; @@ -41,6 +42,7 @@ */ public class FeatureResult { + private final Results results; private final Feature feature; private final String displayName; private final List scenarioResults = new ArrayList(); @@ -101,7 +103,12 @@ public List getStepResults() { return list; } - public FeatureResult(Feature feature) { + public Results getResults() { + return results; + } + + public FeatureResult(Results results, Feature feature) { + this.results = results; this.feature = feature; displayName = FileUtils.removePrefix(feature.getRelativePath()); } diff --git a/karate-core/src/main/java/com/intuit/karate/driver/DevToolsDriver.java b/karate-core/src/main/java/com/intuit/karate/driver/DevToolsDriver.java index 5ba36d46a..481f1ebb4 100644 --- a/karate-core/src/main/java/com/intuit/karate/driver/DevToolsDriver.java +++ b/karate-core/src/main/java/com/intuit/karate/driver/DevToolsDriver.java @@ -640,7 +640,7 @@ public Map cookie(String name) { } @Override - public void setCookie(Map cookie) { + public void cookie(Map cookie) { if (cookie.get("url") == null && cookie.get("domain") == null) { cookie = new HashMap(cookie); // don't mutate test cookie.put("url", currentUrl); diff --git a/karate-core/src/main/java/com/intuit/karate/driver/Driver.java b/karate-core/src/main/java/com/intuit/karate/driver/Driver.java index 44f916a95..204c40c0e 100644 --- a/karate-core/src/main/java/com/intuit/karate/driver/Driver.java +++ b/karate-core/src/main/java/com/intuit/karate/driver/Driver.java @@ -80,14 +80,14 @@ default byte[] screenshot() { } Map cookie(String name); + + void cookie(Map cookie); void deleteCookie(String name); void clearCookies(); - List getCookies(); // getter - - void setCookie(Map cookie); // setter + List getCookies(); // getter void dialog(boolean accept); diff --git a/karate-core/src/main/java/com/intuit/karate/driver/WebDriver.java b/karate-core/src/main/java/com/intuit/karate/driver/WebDriver.java index 5748e3e5c..517b0b23a 100644 --- a/karate-core/src/main/java/com/intuit/karate/driver/WebDriver.java +++ b/karate-core/src/main/java/com/intuit/karate/driver/WebDriver.java @@ -401,7 +401,7 @@ public Map cookie(String name) { } @Override - public void setCookie(Map cookie) { + public void cookie(Map cookie) { http.path("cookie").post(Collections.singletonMap("cookie", cookie)); } diff --git a/karate-core/src/main/java/cucumber/api/cli/Main.java b/karate-core/src/main/java/cucumber/api/cli/Main.java index e82ad32b3..f70b3664c 100644 --- a/karate-core/src/main/java/cucumber/api/cli/Main.java +++ b/karate-core/src/main/java/cucumber/api/cli/Main.java @@ -23,8 +23,6 @@ */ package cucumber.api.cli; -import com.intuit.karate.IdeUtils; - /** * replaces cucumber-jvm code * @@ -33,7 +31,7 @@ public class Main { public static void main(String[] args) { - IdeUtils.exec(args); + com.intuit.karate.cli.Main.main(args); System.exit(0); } diff --git a/karate-core/src/test/java/com/intuit/karate/IdeUtilsTest.java b/karate-core/src/test/java/com/intuit/karate/IdeUtilsTest.java index b285e015b..bddd6912b 100644 --- a/karate-core/src/test/java/com/intuit/karate/IdeUtilsTest.java +++ b/karate-core/src/test/java/com/intuit/karate/IdeUtilsTest.java @@ -23,6 +23,7 @@ */ package com.intuit.karate; +import com.intuit.karate.cli.Main; import static org.junit.Assert.*; import org.junit.Test; @@ -42,14 +43,14 @@ public class IdeUtilsTest { public void testExtractingFeaturePathFromCommandLine() { String expected = "classpath:com/intuit/karate/junit4/demos/users.feature"; String cwd = "/Users/pthomas3/dev/zcode/karate/karate-junit4"; - StringUtils.Pair path = IdeUtils.parseCommandLine(INTELLIJ1, cwd); + StringUtils.Pair path = Main.parseCommandLine(INTELLIJ1, cwd); assertEquals(expected, path.left); assertEquals("^get users and then get first by id$", path.right); - path = IdeUtils.parseCommandLine(ECLIPSE1, cwd); + path = Main.parseCommandLine(ECLIPSE1, cwd); assertEquals(expected, path.left); - path = IdeUtils.parseCommandLine(INTELLIJ2, cwd); + path = Main.parseCommandLine(INTELLIJ2, cwd); assertEquals("classpath:com/intuit/karate/junit4/demos", path.left); - path = IdeUtils.parseCommandLine(INTELLIJ3, cwd); + path = Main.parseCommandLine(INTELLIJ3, cwd); assertEquals("classpath:com/intuit/karate/junit4/demos/users.feature", path.left); assertEquals("^create and retrieve a cat$", path.right); } diff --git a/karate-core/src/test/java/com/intuit/karate/cli/CliExecutionHookTest.java b/karate-core/src/test/java/com/intuit/karate/cli/CliExecutionHookTest.java new file mode 100644 index 000000000..1d36316d9 --- /dev/null +++ b/karate-core/src/test/java/com/intuit/karate/cli/CliExecutionHookTest.java @@ -0,0 +1,16 @@ +package com.intuit.karate.cli; + +import org.junit.Test; + +/** + * + * @author pthomas3 + */ +public class CliExecutionHookTest { + + @Test + public void testCli() { + Main.main(new String[]{"-t", "~@ignore", "-T", "2", "classpath:com/intuit/karate/multi-scenario.feature"}); + } + +} diff --git a/karate-demo/src/test/java/demo/hooks/hooks.feature b/karate-demo/src/test/java/demo/hooks/hooks.feature index 3de86276a..221180d5e 100644 --- a/karate-demo/src/test/java/demo/hooks/hooks.feature +++ b/karate-demo/src/test/java/demo/hooks/hooks.feature @@ -51,5 +51,6 @@ Scenario Outline: | foo + 2 | Scenario: 'after' hooks do not apply to called features - # 'afterScenario' and 'afterFeature' are NOT supported in 'called' features + # 'afterScenario' and 'afterFeature' only work in the "top-level" feature + # and are NOT supported in 'called' features * def result = call read('called.feature') diff --git a/karate-demo/src/test/java/driver/core/test-01.feature b/karate-demo/src/test/java/driver/core/test-01.feature index 1891b9c98..e2c8b9ff2 100644 --- a/karate-demo/src/test/java/driver/core/test-01.feature +++ b/karate-demo/src/test/java/driver/core/test-01.feature @@ -78,7 +78,7 @@ Scenario Outline: using # set cookie Given def cookie2 = { name: 'hello', value: 'world' } - When driver.cookie = cookie2 + When driver.cookie(cookie2) Then match driver.cookies contains '#(^cookie2)' # delete cookie diff --git a/karate-junit4/src/main/java/com/intuit/karate/junit4/FeatureInfo.java b/karate-junit4/src/main/java/com/intuit/karate/junit4/FeatureInfo.java index c381ddaf3..3fb32e3c8 100644 --- a/karate-junit4/src/main/java/com/intuit/karate/junit4/FeatureInfo.java +++ b/karate-junit4/src/main/java/com/intuit/karate/junit4/FeatureInfo.java @@ -71,7 +71,7 @@ public FeatureInfo(Feature feature, String tagSelector) { description = Description.createSuiteDescription(getFeatureName(feature), feature.getResource().getPackageQualifiedName()); FeatureContext featureContext = new FeatureContext(null, feature, tagSelector); CallContext callContext = new CallContext(null, true, this); - exec = new ExecutionContext(System.currentTimeMillis(), featureContext, callContext, null, null, null); + exec = new ExecutionContext(null, System.currentTimeMillis(), featureContext, callContext, null, null, null); unit = new FeatureExecutionUnit(exec); unit.init(); for (ScenarioExecutionUnit u : unit.getScenarioExecutionUnits()) { diff --git a/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java b/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java index 64b9e4438..4d6399985 100644 --- a/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java +++ b/karate-junit5/src/main/java/com/intuit/karate/junit5/FeatureNode.java @@ -53,7 +53,7 @@ public FeatureNode(Feature feature, String tagSelector) { this.feature = feature; FeatureContext featureContext = new FeatureContext(null, feature, tagSelector); CallContext callContext = new CallContext(null, true); - exec = new ExecutionContext(System.currentTimeMillis(), featureContext, callContext, null, null, null); + exec = new ExecutionContext(null, System.currentTimeMillis(), featureContext, callContext, null, null, null); featureUnit = new FeatureExecutionUnit(exec); featureUnit.init(); List selected = new ArrayList(); diff --git a/karate-netty/README.md b/karate-netty/README.md index 62731c68e..3c196d600 100644 --- a/karate-netty/README.md +++ b/karate-netty/README.md @@ -218,6 +218,13 @@ The output directory where the `karate.log` file, JUnit XML and Cucumber report java -jar karate.jar -T 5 -t ~@ignore -o /my/custom/dir src/features ``` +#### Clean +The [output directory](#output-directory) will be deleted before the test runs if you use the `-C` option. + +``` +java -jar karate.jar -T 5 -t ~@ignore -C src/features +``` + #### UI The 'default' command actually brings up the [Karate UI](https://github.com/intuit/karate/wiki/Karate-UI). So you can 'double-click' on the JAR or use this on the command-line: ``` diff --git a/karate-netty/src/main/java/com/intuit/karate/Main.java b/karate-netty/src/main/java/com/intuit/karate/Main.java index f4c862a87..7f1308148 100644 --- a/karate-netty/src/main/java/com/intuit/karate/Main.java +++ b/karate-netty/src/main/java/com/intuit/karate/Main.java @@ -25,7 +25,6 @@ import com.intuit.karate.exception.KarateException; import com.intuit.karate.netty.FeatureServer; -import com.intuit.karate.netty.NettyUtils; import com.intuit.karate.ui.App; import java.io.File; import java.util.ArrayList; @@ -88,15 +87,18 @@ public class Main implements Callable { @Parameters(description = "one or more tests (features) or search-paths to run") List tests; - + @Option(names = {"-n", "--name"}, description = "scenario name") - String name; + String name; @Option(names = {"-e", "--env"}, description = "value of 'karate.env'") String env; @Option(names = {"-u", "--ui"}, description = "show user interface") - boolean ui; + boolean ui; + + @Option(names = {"-C", "--clean"}, description = "clean output directory") + boolean clean; public static void main(String[] args) { boolean isOutputArg = false; @@ -141,6 +143,9 @@ public Object handleExecutionException(ExecutionException ex, ParseResult parseR @Override public Void call() throws Exception { + if (clean) { + org.apache.commons.io.FileUtils.deleteDirectory(new File(output)); + } if (tests != null) { if (ui) { App.main(new String[]{new File(tests.get(0)).getAbsolutePath(), env}); diff --git a/karate-ui/src/main/java/com/intuit/karate/ui/AppSession.java b/karate-ui/src/main/java/com/intuit/karate/ui/AppSession.java index d41faa32c..eb0bfd051 100644 --- a/karate-ui/src/main/java/com/intuit/karate/ui/AppSession.java +++ b/karate-ui/src/main/java/com/intuit/karate/ui/AppSession.java @@ -78,7 +78,7 @@ public AppSession(BorderPane rootPane, File workingDir, Feature feature, String logPanel = new LogPanel(); appender = logPanel.appender; FeatureContext featureContext = FeatureContext.forFeatureAndWorkingDir(env, feature, workingDir); - exec = new ExecutionContext(System.currentTimeMillis(), featureContext, callContext, null, null, null); + exec = new ExecutionContext(null, System.currentTimeMillis(), featureContext, callContext, null, null, null); featureUnit = new FeatureExecutionUnit(exec); featureUnit.init(); featureOutlinePanel = new FeatureOutlinePanel(this);