【问题标题】:Selenium [Java] PageFactory Design : Where do I write my Assertions following Page Object ModelSelenium [Java] PageFactory Design:我在哪里写我的断言遵循页面对象模型
【发布时间】:2017-03-25 13:39:58
【问题描述】:

我正在遵循页面对象模型来自动化一个应用程序中的流程。在其中一个模块中,我必须声明页面标题和更多消息。截至目前,我将我的断言代码放在 PageFactory 本身中,如下所示:

public class EditPost {

    WebDriver driver;

    public EditPost(WebDriver editPostDriver)
    {
        this.driver=editPostDriver;
    }

    @FindBy(how=How.XPATH,using="//*[@id='message']/p")
    WebElement post_published;

    public void assert_message()
    {
        String actual_message_title=post_published.getText();
        Assert.assertEquals(actual_message_title, "Post published. View post");
        System.out.println("Message: Post published, Successfully Verified");
    }
}

我正在从实现 TestNG 的主文件中调用断言方法,如下所示:

@Test (priority=5)
public void assert_message()
{
    //Created Page Object using Page Factory
    EditPost edit_post = PageFactory.initElements(driver, EditPost.class);
    edit_post.assert_message();

}

目前,我正在通过 3 个包运行执行。浏览器工厂的“Helper”包,PageFactories 的“Pages”包和测试用例的“Testcase”包。

我的目标是向前发展,我想重用为所有不同实用程序编写的代码。

我的问题是:

  1. 根据 PageFactory 和页面对象模型的概念,我的方法是否正确?还是我需要将断言移动到“帮助”包?或者我应该为断言创建一个单独的库/包? (在接下来的日子里,我可能需要在一个页面上执行多个断言)

  2. 在下一个 sprint 中,我可能需要执行一些其他活动,例如截取所有/失败的测试用例的屏幕截图。那么如何保持我的设计井井有条,以便我可以重用代码/库/以最佳方式利用它们?

【问题讨论】:

  • IMO 断言应该放在 @Test 标签内的 testcases 类中,因为它们专门用于识别检查点,以确定您的流程是否按计划进行
  • @Kushalツ 谢谢。但是页面标题、页面图标、标签文本和所有与页面相关的属性不是都在PageFactory中找到了吗?
  • 是的,可以做到;但是您必须为每个页面类中的断言编写特定的方法
  • 是的,这就是我现在正在做的事情。但我不确定这是否是理想地保存它们的确切位置。但同样,就像验证页面标题、图标和某些其他元素一样,我更愿意重用代码。所以从那时起,我觉得我应该把它们放在 Helper 包或其他包中。

标签: java selenium design-patterns pageobjects


【解决方案1】:

根据我见过的大多数网站,最佳做法是将断言保留在页面对象之外。下面是 Selenium 文档中的一个示例。

http://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern

页面对象的设计方式有很大的灵活性,但有一些基本规则可以让您的测试代码获得所需的可维护性。

页面对象本身不应该进行验证或断言。这是您测试的一部分,应该始终在测试代码中,而不是在页面对象中。页面对象将包含页面的表示,以及页面通过方法提供的服务,但与正在测试的内容相关的代码不应包含在页面对象中。

有一个单一的验证可以并且应该在页面对象内,即验证页面以及页面上可能的关键元素是否已正确加载。此验证应在实例化页面对象时完成。在上面的示例中,SignInPage 和 HomePage 构造函数都检查预期页面是否可用并准备好接受来自测试的请求。

页面对象应返回产品名称、产品价格、当前选择的数量等内容。然后测试代码会断言返回的字符串与预期的匹配。

assert_message() 将变为getMessage() 并将消息作为String 返回。见下文。

public String getMessage()
{
    return driver.findElement(messageLocator).getText();
}

(注意:请继续阅读我将PageFactory 元素更改为定位器的原因。)

然后在您的测试代码中,您将拥有

Assert.assertEquals(editPost.getMessage(), "Post published. View post");

现在您已将断言代码保留在测试脚本中,并保留在页面对象之外。

看看你的代码,我会提出一些进一步的建议。

  1. 我建议您阅读一些 Java 命名约定。有许多网站都有推荐,我认为它们之间有很多相似之处,但这里是 oracle recommendations 开始。您的方法名称应该是

    动词,混合大小写,首字母小写,每个内部单词的首字母大写。

    所以assert_message() 会变成assertMessage() 等等。 _s 使它看起来更像 python。

  2. 定位器的优先顺序:ID、CSS 选择器,以及在极少数情况下的 XPath。 ID 应该始终是您的首选,因为它(根据 W3C 定义)在页面上应该是唯一的。 CSS 选择器应该是下一个,因为它是最快的(在我的测试中比 ID 更快),拥有最好的浏览器支持,并且在浏览器中最一致地实现。 XPath 应该只保留用于 CSS 选择器无法完成的事情,例如通过包含的文本查找元素。与 CSS 选择器相比,XPath 定位器的性能较差,并且没有与 CSS 选择器相同级别的支持。例如,您的 XPath 定位器可以轻松转换为 CSS 选择器“#message > p”。

    这里有一些 CSS 选择器参考可以帮助您入门。

    CSS Selectors reference

    CSS Selector tips

  3. 删除PageFactory。是的,它似乎让事情变得更容易,但我认为在许多情况下它会导致更多问题,比如过时的元素异常等。而是根据需要抓取页面。在类的顶部声明所有定位器,并在需要时在方法中使用它们。

    public class EditPost {
    
        WebDriver driver;
    
        By messageLocator = By.cssSelector("#message > p")
    
        public EditPost(WebDriver editPostDriver)
        {
            this.driver = editPostDriver;
        }
    
        public String getMessage()
        {
            return driver.findElement(messageLocator).getText();
        }
    }
    

我知道这超出了您的要求,但希望对您有所帮助。

【讨论】:

  • 我喜欢您对 PageFactory 的评论。我自己也担心缓存问题,因此避免这种情况似乎是合适的。
  • 我们正在将一个项目从 Selenium-ruby 迁移到 Selenium-java。 Ruby 中有一些成熟的“宝石”,使使用 PO 变得非常容易。我想知道Java是否有类似的东西。如果不出意外,汇编最佳实践就可以了:)
  • @HakunaM 据我所知,Java 没有等效的库......至少我没有听说过和使用过。我只是自己写的。我遵循的基础是:定位器是类的私有属性,方法被命名为操作并表示用户可以在页面上执行的操作,用户不需要了解页面的 HTML 即可使用方法,一切都与给定的页面应该在一个适当命名的页面对象内,等等。
  • @JeffC - 你能帮我解决一个相关的问题吗stackoverflow.com/questions/55719153/… ?谢谢。
猜你喜欢
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多