我试图将Cucumber特征文件中的WebElement(而不是String)传递给它的相应步骤定义。
Scenario: Test
Given I want to click "myWebElement"
相应的步骤定义为:
@Given("^I want to click (.*)$")
public void Test(WebElement we) {
we.click();
}
在运行时,我得到以下跟踪:
cucumber.runtime.CucumberException: Don't know how to convert ""myWebElement"" into org.openqa.selenium.WebElement.
Try writing your own converter:
@cucumber.deps.com.thoughtworks.xstream.annotations.XStreamConverter(WebElementConverter.class)
public class WebElement {}
at cucumber.runtime.ParameterInfo.convert(ParameterInfo.java:150)
at cucumber.runtime.StepDefinitionMatch.transformedArgs(StepDefinitionMatch.java:68)
at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
at cucumber.runtime.Runtime.runStep(Runtime.java:299)
at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44)
at cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165)
at cucumber.api.testng.TestNGCucumberRunner.runCucumber(TestNGCucumberRunner.java:63)
at cucumber.api.testng.AbstractTestNGCucumberTests.feature(AbstractTestNGCucumberTests.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
是否有可以为这样的"转换器"?
编写的功能感谢。
答案 0 :(得分:3)
首先,您需要问问自己为什么要将WebElement
作为参数传递给BDD框架。
BDD测试框架通常用于验收测试,因此参数应该是利益相关者可以理解的。
现在,为了得到答案,Cucumber使用所谓的变形金刚来实现这一目标。取自Cucumber文档:
public abstract class Transformer extends Object implements cucumber.deps.com.thoughtworks.xstream.converters.SingleValueConverter 允许将步骤定义参数转换为自定义类型, 让您完全控制该类型的实例化方式。
考虑以下Gherkin步骤:
鉴于今天的日期是" 10/03 / 1985"举个例子,我们假设我们想要 黄瓜改造子串" 10/03 / 1985"进入一个实例 org.joda.time.LocalDate类:
@Given("today's date is \"(.*)\"") public void todays_date_is(LocalDate d) { } If the parameter's class has a constructor with a single String or Object argument, then Cucumber will instantiate it without
任何进一步的麻烦。但是,在这种情况下可能不会给你什么 你要。根据您的区域设置,日期可能是10月3日或3月10日!
这是您可以使用自定义变压器的时候。你也必须这样做 如果你的参数类没有一个构造函数 字符串或对象参数。对于JODA时间示例:
@Given("today's date is \"(.*)\"") public void todays_date_is(@Transform(JodaTimeConverter.class) LocalDate d) { } And then a JodaTimeConverter class: public static class JodaTimeConverter extends Transformer<LocalDate> { private static DateTimeFormatter FORMATTER = DateTimeFormat.forStyle("S-"); @Override public LocalDate transform(String value) { return FORMATTER.withLocale(getLocale()).parseLocalDate(value); } } An alternative to annotating parameters with Transform is to annotate your class with XStreamConverter: @XStreamConverter(MyConverter.class) public class MyClass { } This will also enable a DataTable to be transformed to a List<MyClass;>
我还没有用WebElement
类型尝试过,但原理是一样的。
您可以找到更多信息here。
答案 1 :(得分:0)
我知道这个问题是针对Java的,但这是我为C#中的相同要求所做的工作。我只是为了帮助来到这里的人为同一问题在C#中寻找解决方案
您可以在c#黄瓜/ specflow中使用[StepArgumentTransformation]
来实现
Scenario Outline: examples with step argument
Given we have '<Webelements>'
Examples:
| Webelements |
| Gmail |
步骤定义为:
using TechTalk.SpecFlow;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using NUnit.Framework;
[Binding]
public class Browser
{
private readonly BrowserDriver _browserDriver;
public static OpenQA.Selenium.IWebDriver driver ;
public Browser(BrowserDriver browserDriver, FeatureContext featureContext)
{
_browserDriver = browserDriver; //your chrome driver
driver = _browserDriver._driver;
_featureContext = featureContext;
_featureContext.Add("driver", driver);
}
[Given(@"we have '(.*)'")]
public void webelements(ChromeWebElement o)
{
Assert.False(o.Displayed);
}
[StepArgumentTransformation]
public ChromeWebElement convertToWebElement(string c)
{
ChromeDriver parent = _featureContext.Get<ChromeDriver>("driver");
return new ChromeWebElement(parent, c);
}
很明显,您得到结果element is not attached to the page document
,因为我只是将Gmail
元素用于测试目的
答案 2 :(得分:-1)
实现此目的的标准方法是提供定位器或定位器的引用作为step参数,并在step中使用create元素。例如,使用qaf,您可以执行以下步骤:
import static com.qmetry.qaf.automation.ui.webdriver.ElementFactory.$;
...
@Given("^I want to click (.*)$")
public void click(String eleLoc) {
$("eleLoc").click();
}
//blow is example using qaf step annotation
//that doesn't need regex...
@QAFTestStep(description="I want to click {element}")
public void click(String eleLoc) {
$("eleLoc").click();
}
可以在特征文件中调用以下步骤:
Scenario: Test
Given I want to click "name=q"
如果您使用的是locator repository,则可能如下所示:
mypage_locators.properties
page.myWebElement=name=q
#add other locators for this page
下面的self descriptive value是上面相同的定位符
page.myWebElement={"locator":"name=q", "desc":"search text box on search page"}
可以在特征文件中调用以下步骤:
Scenario: Test
Given I want to click "page.myWebElement"
您可以使用或引用适用于web,mobile,perfecto和web-services的内置步骤,也可以使用自定义步骤实现。