我想在场景中添加一个标签@skiponchrome,这应该会在使用Chrome浏览器运行Selenium测试时跳过这个场景。这样做的原因是因为某些场景在某些环境中工作而在其他环境中不起作用,这可能甚至不是特定于浏览器测试的,并且可以应用于其他情况,例如OS平台。
示例钩子:
@Before("@skiponchrome") // this works
public void beforeScenario() {
if(currentBrowser == 'chrome') { // this works
// Skip scenario code here
}
}
我知道可以在黄瓜标签中定义〜@ skiponchrome来跳过标签,但我想在运行时跳过标签。这样,当我在特定环境中开始测试运行时,我不必考虑提前跳过哪些步骤。
我想创建一个钩子来捕获标记并跳过场景而不报告失败/错误。这可能吗?
答案 0 :(得分:5)
我真的更喜欢通过为每个环境定义单独的运行配置来明确运行哪些测试。我还希望将我使用的标签数量保持在最低限度,以保持配置数量的可管理性。
我不认为只用标签就可以达到你想要的效果。您需要编写一个自定义的jUnit测试运行器来代替@RunWith(Cucumber.class)。看看Cucumber实现,看看它是如何工作的。您需要根据浏览器或其他运行时条件更改RuntimeOptionsFactory创建的RuntimeOptions以包含/排除标记。
或者,您可以考虑编写一个小脚本来调用您的测试套件,根据您正在运行的环境构建一个动态包含/排除的标记列表。我会认为这是一个更多可维护,清洁的解决方案。
答案 1 :(得分:5)
我意识到这是对已经回答的问题的后期更新,但我想通过cucumber-jvm直接添加一个选项supported:
@Before //(cucumber one)
public void setup(){
Assume.assumeTrue(weAreInPreProductionEnvironment);
}
“如果weAreInPreProductionEnvironment
为假,则该方案将被标记为已忽略(但测试将通过)。”
您需要添加
import org.junit.Assume;
与接受的答案的主要区别在于JUnit assume failures behave just like pending
重要由于bug fix,您需要使用cucumber-jvm版本1.2.5,截至撰写本文时,这是最新版本。例如,上面的内容将在cucumber-java8-1.2.3.jar
中生成失败而不是pending答案 2 :(得分:4)
我也有同样的挑战,我需要在运行时动态地从应用程序中获取的标志跳过运行方案,这表明在应用程序上是否启用了要测试的功能。不..
所以这就是我在scenario文件中编写逻辑的方法,我们在每个步骤都有胶水代码。
我使用了一个独特的标签'@ Feature-01AXX'来标记我的场景,只有当应用程序上有该功能(代码)时才需要运行。
因此,对于每个场景,首先检查标签'@ Feature-01XX',如果它存在,则检查该功能的可用性,然后才选择该场景进行运行。否则它只会被跳过,而Junit不会将此标记为失败,而是将其标记为Pass。因此,如果由于功能不可用而未运行这些测试的最终结果将会通过,那很酷......
@Before
public void before(final Scenario scenario) throws Exception {
/*
my other pre-setup tasks for each scenario.
*/
// get all the scenario tags from the scenario head.
final ArrayList<String> scenarioTags = new ArrayList<>();
scenarioTags.addAll(scenario.getSourceTagNames());
// check if the feature is enabled on the appliance, so that the tests can be run.
if (checkForSkipScenario(scenarioTags)) {
throw new AssumptionViolatedException("The feature 'Feature-01AXX' is not enabled on this appliance, so skipping");
}
}
private boolean checkForSkipScenario(final ArrayList<String> scenarioTags) {
// I use a tag "@Feature-01AXX" on the scenarios which needs to be run when the feature is enabled on the appliance/application
if (scenarioTags.contains("@Feature-01AXX") && !isTheFeatureEnabled()) { // if feature is not enabled, then we need to skip the scenario.
return true;
}
return false;
}
private boolean isTheFeatureEnabled(){
/*
my logic to check if the feature is available/enabled on the application.
in my case its an REST api call, I parse the JSON and check if the feature is enabled.
if it is enabled return 'true', else return 'false'
*/
}
答案 3 :(得分:3)
实际上这很容易。如果你挖掘Cucumber-JVM和JUnit 4源代码,你会发现JUnit在运行时很容易跳过(只是没有文档)。
查看JUnit 4 ParentRunner
的以下源代码,其中Cucumber-JVM的FeatureRunner
(用于Cucumber
,默认的Cucumber运行者):
@Override
public void run(final RunNotifier notifier) {
EachTestNotifier testNotifier = new EachTestNotifier(notifier,
getDescription());
try {
Statement statement = classBlock(notifier);
statement.evaluate();
} catch (AssumptionViolatedException e) {
testNotifier.fireTestIgnored();
} catch (StoppedByUserException e) {
throw e;
} catch (Throwable e) {
testNotifier.addFailure(e);
}
}
这就是JUnit决定显示结果的方式。如果它成功,它将显示一个传递,但在JUnit中可能@Ignore
,那么在这种情况下会发生什么?好吧,AssumptionViolatedException
(或者在这种情况下为黄瓜RunNotifier
)会抛出FeatureRunner
。
所以你的例子变成了:
@Before("@skiponchrome") // this works
public void beforeScenario() {
if(currentBrowser == 'chrome') { // this works
throw new AssumptionViolatedException("Not supported on Chrome")
}
}
如果你以前使用过vanilla JUnit 4,你会记得@Ignore
收到跑步者忽略测试时显示的可选信息。 AssumptionViolatedException
包含消息,因此您应该在以这种方式跳过测试后在测试输出中看到它,而无需编写自己的自定义运行器。
答案 4 :(得分:1)
我已经实现了一个定制的junit运行器,如下所示。这个想法是在运行时添加标签。
因此,对于需要新用户的方案,我们将方案标记为“ @requires_new_user”。然后,如果我们在一个环境中(例如,不允许您轻松注册新用户的生产环境)进行测试,那么我们将发现我们无法获得新用户。然后,将““ not @requires_new_user”添加到黄瓜选项中以跳过该情况。
这是我现在能想到的最干净的解决方案。
public class WebuiCucumberRunner extends ParentRunner<FeatureRunner> {
private final JUnitReporter jUnitReporter;
private final List<FeatureRunner> children = new ArrayList<FeatureRunner>();
private final Runtime runtime;
private final Formatter formatter;
/**
* Constructor called by JUnit.
*
* @param clazz the class with the @RunWith annotation.
* @throws java.io.IOException if there is a problem
* @throws org.junit.runners.model.InitializationError if there is another problem
*/
public WebuiCucumberRunner(Class clazz) throws InitializationError, IOException {
super(clazz);
ClassLoader classLoader = clazz.getClassLoader();
Assertions.assertNoCucumberAnnotatedMethods(clazz);
RuntimeOptionsFactory runtimeOptionsFactory = new RuntimeOptionsFactory(clazz);
RuntimeOptions runtimeOptions = runtimeOptionsFactory.create();
addTagFiltersAsPerTestRuntimeEnvironment(runtimeOptions);
ResourceLoader resourceLoader = new MultiLoader(classLoader);
runtime = createRuntime(resourceLoader, classLoader, runtimeOptions);
formatter = runtimeOptions.formatter(classLoader);
final JUnitOptions junitOptions = new JUnitOptions(runtimeOptions.getJunitOptions());
final List<CucumberFeature> cucumberFeatures = runtimeOptions.cucumberFeatures(resourceLoader, runtime.getEventBus());
jUnitReporter = new JUnitReporter(runtime.getEventBus(), runtimeOptions.isStrict(), junitOptions);
addChildren(cucumberFeatures);
}
private void addTagFiltersAsPerTestRuntimeEnvironment(RuntimeOptions runtimeOptions)
{
String channel = Configuration.TENANT_NAME.getValue().toLowerCase();
runtimeOptions.getTagFilters().add("@" + channel);
if (!TestEnvironment.getEnvironment().isNewUserAvailable()) {
runtimeOptions.getTagFilters().add("not @requires_new_user");
}
}
...
}
或者您可以扩展官方的Cucumber Junit测试运行程序cummon.api.junit.Cucumber和覆盖方法
/**
* Create the Runtime. Can be overridden to customize the runtime or backend.
*
* @param resourceLoader used to load resources
* @param classLoader used to load classes
* @param runtimeOptions configuration
* @return a new runtime
* @throws InitializationError if a JUnit error occurred
* @throws IOException if a class or resource could not be loaded
* @deprecated Neither the runtime nor the backend or any of the classes involved in their construction are part of
* the public API. As such they should not be exposed. The recommended way to observe the cucumber process is to
* listen to events by using a plugin. For example the JSONFormatter.
*/
@Deprecated
protected Runtime createRuntime(ResourceLoader resourceLoader, ClassLoader classLoader,
RuntimeOptions runtimeOptions) throws InitializationError, IOException {
ClassFinder classFinder = new ResourceLoaderClassFinder(resourceLoader, classLoader);
return new Runtime(resourceLoader, classFinder, classLoader, runtimeOptions);
}
您可以根据需要在此处操作runtimeOptions。但是该方法被标记为已弃用,因此请谨慎使用。
答案 5 :(得分:0)
如果你正在使用Maven,你可以阅读使用浏览器配置文件,然后在那里设置相应的~exclude标签吗?
除非你问如何从命令行运行它,在这种情况下你用@skipchrome标记场景然后当你运行黄瓜时将黄瓜选项设置为tags = {“〜@ skipchrome”}
答案 6 :(得分:0)
如果只希望暂时跳过某个场景(例如,在编写场景时),则可以将其注释掉(在Eclipse或Intellij中为ctrl
+ /
)。