0

我正在尝试将 Cucumber 功能文件中的 WebElement(而不是字符串)传递到其相应的步骤定义中。

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)

有没有可以为这样的“转换器”编写的函数?

谢谢。

4

3 回答 3

4

首先,您需要问自己为什么要将 aWebElement作为参数传递给 BDD 框架。BDD 测试框架通常用于验收测试,因此即使利益相关者也应该可以理解参数。

现在,为了得到你的答案,Cucumber 使用所谓的 Transformers 来实现这一点。取自 Cucumber 文档:

public abstract class Transformer extends Object implements cucumber.deps.com.thoughtworks.xstream.converters.SingleValueConverter 允许将步骤定义参数转换为自定义类型,让您完全控制该类型的实例化方式。

考虑以下 Gherkin 步骤:

假设今天的日期是“10/03/1985”作为示例,假设我们希望 Cucumber 将子字符串“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 日!

这是您可以使用自定义转换器的时候。如果您的参数类没有带有单个 String 或 Object 参数的构造函数,您也必须这样做。对于 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类型,但原理是一样的。您可以在此处找到更多信息。

于 2016-08-23T13:17:35.383 回答
0

我知道这个问题是针对 java 的,但这是我在 C# 中针对相同要求所做的。我添加只是为了帮助任何来这里寻找相同问题的 c# 解决方案的人

您可以[StepArgumentTransformation]在 c# cucumber/specflow中实现这一点

  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元素用于测试目的

于 2020-05-22T16:01:08.870 回答
-1

实现这一点的标准方法是提供定位器或定位器的引用作为步骤参数,并使用步骤中的创建元素。例如,使用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"

如果您使用的是定位器存储库,它可能如下所示:

mypage_locators.properties

page.myWebElement=name=q 
#add other locators for this page

以下是上述同一定位器的自我描述值

page.myWebElement={"locator":"name=q", "desc":"search text box on search page"}

步骤可以在功能文件中调用,如下所示:

Scenario: Test
    Given I want to click "page.myWebElement"

您可以使用或参考可用于webmobileperfectoweb-services的内置步骤,您也可以拥有自定义步骤实现。

于 2019-04-12T22:04:49.210 回答