我需要这样做,以便在执行用于报告、日志记录等的方法之前,可以将所需的参数传递给类,这样就可以并行执行测试用例。在将关键字驱动selenium框架转换为BDD Gherkin selenium框架.In关键字驱动框架的过程中,我从Excel获取关键字,在执行方法之前通过Java反射将所需的参数传递给类。
String [] argv = new String[]{
"-g"
,"businesscomponents"
,"./Features"
//,"-t","@P1,@P2"
,"-n","Validate_login_search_using_sku_id"
};
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
byte exitstatus = Main.run(argv, contextClassLoader);发布于 2018-05-25 20:30:04
这比我想象的要容易得多。这只需要修改一个类(Runtime.java)的几行代码,以确定所有的钩子和步骤方法。然后,它所需要的就是在dryrun模式下运行,将其设置为true,以获得所有细节。
覆盖Runtime.java行为-
3.在私有方法中,runHooks(第209行)注释掉了第210和214行。
private void runHooks(List<HookDefinition> hooks, Reporter reporter, Set<Tag> tags, boolean isBefore) {
//if (!runtimeOptions.isDryRun()) {
for (HookDefinition hook : hooks) {
runHookIfTagsMatch(hook, reporter, tags, isBefore);
}
//}
}if(!runtimeOptions.isDryRun()) hook.execute(scenarioResult);CustomFormatter -现在将将所有细节存储在ThreadLocal变量中。
public class CustomFormatter implements Reporter, Formatter {
private Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails;
private Map<Scenario, List<StepDefinitionMatch>> scenarioDetails;
private List<StepDefinitionMatch> stepDetails;
private String featureUri = "";
private Scenario scenario;
private Map<Scenario, List<Match>> beforeHooks;
private Map<Scenario, List<Match>> afterHooks;
private List<Match> beforeMatches;
private List<Match> afterMatches;
public CustomFormatter() {
featureDetails = new LinkedHashMap<>();
beforeHooks = new LinkedHashMap<>();
afterHooks = new LinkedHashMap<>();
}
@Override
public void before(Match match, Result result) {
beforeMatches.add(match);
}
@Override
public void result(Result result) {
}
@Override
public void after(Match match, Result result) {
afterMatches.add(match);
}
@Override
public void match(Match match) {
//ThreadLocalStepDefinitionMatch.set((StepDefinitionMatch) match);
stepDetails.add((StepDefinitionMatch) match);
}
@Override
public void embedding(String mimeType, byte[] data) {
}
@Override
public void write(String text) {
}
@Override
public void syntaxError(String state, String event,
List<String> legalEvents, String uri, Integer line) {
}
@Override
public void uri(String uri) {
featureUri = uri;
}
@Override
public void feature(Feature feature) {
scenarioDetails = new LinkedHashMap<>();
}
@Override
public void scenarioOutline(ScenarioOutline scenarioOutline) {
}
@Override
public void examples(Examples examples) {
}
@Override
public void startOfScenarioLifeCycle(Scenario scenario) {
this.scenario = scenario;
stepDetails = new ArrayList<>();
beforeMatches = new ArrayList<>();
afterMatches = new ArrayList<>();
}
@Override
public void background(Background background) {
}
@Override
public void scenario(Scenario scenario) {
}
@Override
public void step(Step step) {
}
@Override
public void endOfScenarioLifeCycle(Scenario scenario) {
scenarioDetails.put(this.scenario, stepDetails);
beforeHooks.put(this.scenario, beforeMatches);
afterHooks.put(this.scenario, afterMatches);
}
@Override
public void done() {
}
@Override
public void close() {
/*System.out.println(featureDetails);
System.out.println(beforeHooks);
System.out.println(afterHooks);*/
StepHookDetails shd = new StepHookDetails(featureDetails, beforeHooks, afterHooks);
ThreadLocalStepHookDetails.set(shd);
}
@Override
public void eof() {
featureDetails.put(featureUri, scenarioDetails);
}
}如果取消了close()方法中的打印行注释,就可以看到输出如下所示。
Step方法匹配-对应于Map - Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails in CustomFormatter class
{src/test/resources/features/format2.feature={gherkin.formatter.model.Scenario@38d8f54a=cucumber.runtime.StepDefinitionMatch@6236eb5f,cucumber.runtime.StepDefinitionMatch@7c1e2a9e,gherkin.formatter.model.Scenario@49e53c76=cucumber.runtime.StepDefinitionMatch@fa36558,cucumber.runtime.StepDefinitionMatch@672872e1}}
在Hook将-Corresponds与Map - Map<Scenario, List<Match>> beforeHooks in CustomFormatter class匹配之前
{gherkin.formatter.model.Scenario@38d8f54a=gherkin.formatter.model.Match@32910148,gherkin.formatter.model.Scenario@49e53c76=gherkin.formatter.model.Match@3f56875e}
Hook Matches -Corresponds to Map - Map<Scenario, List<Match>> afterHooks in CustomFormatter class
{gherkin.formatter.model.Scenario@38d8f54a=gherkin.formatter.model.Match@2b4bac49,gherkin.formatter.model.Scenario@49e53c76=gherkin.formatter.model.Match@fd07cbb}
这是运行一个功能文件,如下所示。如果您有多个特性文件,您将在featureDetails地图中有多个特征键。钩子将被添加到钩子地图。
Feature: Validating sample Two
Background:
Given user gets count from "Car0"
@Format
Scenario: Scenario Two
And user gets count from "Car1"
@Format
Scenario: Scenario Two
And user gets count from "Car1"重要--将三者绑定在一起的关键是Scenario对象。如果可用,可以很容易地迭代featureDetails映射并获得前钩子,然后是可用的步骤,然后是之后的钩子。用于获取钩子方法名称
ThreadLocal类-
public class ThreadLocalStepHookDetails {
private static final ThreadLocal<StepHookDetails> threadStepHookDetails = new InheritableThreadLocal<StepHookDetails>();
private ThreadLocalStepHookDetails() {
}
public static StepHookDetails get() {
return threadStepHookDetails.get();
}
public static void set(StepHookDetails match) {
threadStepHookDetails.set(match);
}
public static void remove() {
threadStepHookDetails.remove();
}
}StepHookDetails类-
public class StepHookDetails {
private Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails;
private Map<Scenario, List<Match>> beforeHooks;
private Map<Scenario, List<Match>> afterHooks;
public StepHookDetails() {}
public StepHookDetails(
Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails,
Map<Scenario, List<Match>> beforeHooks,
Map<Scenario, List<Match>> afterHooks) {
this.featureDetails = featureDetails;
this.beforeHooks = beforeHooks;
this.afterHooks = afterHooks;
}
public Map<String, Map<Scenario, List<StepDefinitionMatch>>> getFeatureDetails() {
return featureDetails;
}
public void setFeatureDetails(
Map<String, Map<Scenario, List<StepDefinitionMatch>>> featureDetails) {
this.featureDetails = featureDetails;
}
public Map<Scenario, List<Match>> getBeforeHooks() {
return beforeHooks;
}
public void setBeforeHooks(Map<Scenario, List<Match>> beforeHooks) {
this.beforeHooks = beforeHooks;
}
public Map<Scenario, List<Match>> getAfterHooks() {
return afterHooks;
}
public void setAfterHooks(Map<Scenario, List<Match>> afterHooks) {
this.afterHooks = afterHooks;
}
}检查商店中的详细信息-
您可以使用下面的代码作为示例查看地图中的详细信息并按顺序排列。第二步前
StepHookDetails sd = ThreadLocalStepHookDetails.get();
sd.getFeatureDetails().entrySet().stream().forEach(
e -> e.getValue().entrySet().stream().forEach(
ee -> {
System.out.println(ee.getKey().getLine());
sd.getBeforeHooks().get(ee.getKey()).stream().forEach(bh -> System.out.println(bh.getLocation()));
ee.getValue().stream().forEach(s -> System.out.println(s.getLocation() + " " + s.getArguments()));
sd.getAfterHooks().get(ee.getKey()).stream().forEach(ah -> System.out.println(ah.getLocation()));
}));对于上面的特性文件,得到了以下输出
场景第8行在钩子前第8行()步骤SampleSteps.userGetsCountFromAndStores(String) Car0 Steps SampleSteps.userGetsCountFromAndStores(String) Car1后Hook SampleSteps.afterOne(场景)场景第15行在Hook SampleSteps.before()步骤SampleSteps.userGetsCountFromAndStores(String) Car0 Steps SampleSteps.userGetsCountFromAndStores(String) Car1后Hook SampleSteps.afterOne(场景)
这也将适用于场景大纲。
更新-
Feature: UI Automation
@P1
Scenario: Validate_Home_page
Given the customer opens launches the homepage@Given("^the customer opens launches the homepage$")
public void openbrowser() { }public static void main (String args[]) throws IOException {
String[] argv = new String[] { "-g", "cucumpar.test.stepdefs", "src/test/resources/features/features.feature",
"-t", "@P1" , "-p", "cusform.CustomFormatter","-d"};
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
byte exitstatus = Main.run(argv, contextClassLoader);
----------------
StepHookDetails sd = ThreadLocalStepHookDetails.get();
----------------
}结果
{src/test/resources/features/features.feature={gherkin.formatter.model.Scenario@6771beb3=cucumber.runtime.StepDefinitionMatch@51399530}} {gherkin.formatter.model.Scenario@6771beb3=[]} {gherkin.formatter.model.Scenario@6771beb3=[]}场景行第4步SampleSteps.openbrowser() []
更新
需要向StepDefinitionMatch类添加一些代码。类似于您为Runtime.java所做的工作,请在- https://github.com/cucumber/cucumber-jvm/blob/v1.2.5/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java下载1.2.5类。将该类复制到现有的cucumber.runtime包中。然后添加以下方法--
public List<List<String>> getDataTableData() {
List<List<String>> data = new ArrayList<>();
if(step.getRows()!=null)
step.getRows().forEach(row -> data.add(row.getCells()));
return data;
}就是这样。在现有的打印方法中调用此方法,如下所示。
ee.getValue().stream().forEach(s -> System.out.println("Steps " + s.getLocation() + " " + s.getArguments() + " " + s.getDataTableData()));对于此特性文件
Scenario: Scenario Four
And car gets count
| car | owner |
| Car1 | OwnerOne |
| Car2 | OwnerTwo |
| Car3 | OwnerThree |得到了这个输出--第一行是标题,根据需要定制。
SampleSteps.carGetsCount(DataTable)汽车,车主,Car1,OwnerOne,Car2,OwnerTwo,Car3,OwnerThree]
更新
public Map<String, List<String>> getDataTableData() {
Map<String, List<String>> mapData = new HashMap<>();
if(step.getRows()!=null) {
List<List<String>> data = new ArrayList<>();
step.getRows().forEach(row -> data.add(row.getCells()));
List<String> keys = data.remove(0);
data.stream().forEach(row -> IntStream.range(0, keys.size()).forEach(index -> {
List<String> tempList = new ArrayList<>();
tempList.add(row.get(index));
mapData.compute(keys.get(index), (key, val) -> {
if(val==null)
return tempList;
val.addAll(tempList);
return val;
});
}));
}
return mapData;
}https://stackoverflow.com/questions/50499130
复制相似问题