Selenium [Java] PageFactory Design : Where do I write my Assertions following Page Object Model

喜夏-厌秋 提交于 2019-12-18 07:22:47

问题


I am following Page Object Model to automate a flow in one application. In one of the module I have to assert Page Title and some more messages. As of now I am putting my Assertion code in the PageFactory itself as follows:

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");
    }
}

I am calling the assert methods from the main file implementing TestNG as follows:

@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();

}

Currently, I am running the execution through 3 packages. "Helper" package for the Browser Factory, "Pages" package for the PageFactories and "Testcase" package for the Testcases.

My objective is moving forward I want to reuse the code written for all the different utilities.

My questions are:

  1. As per the concept of PageFactory & Page Object Model is my approach correct? Or do I need to move the Assertions to the "Helper" package? Or should I create a separate library/package for the Assertions? (In the comming days I may need to perform multiple Assertions on a single page)

  2. In the next sprint I may require to do some other activities like taking Screen Shots of All/Failed Testcases. So how do I keep my design structured and organized so I can reuse the code/libraries/utilize them in a optimum way?


回答1:


Best practice, according to most sites I've seen, is to keep the asserts out of the page objects. One example is below from the Selenium docs.

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

There is a lot of flexibility in how the page objects may be designed, but there are a few basic rules for getting the desired maintainability of your test code.

Page objects themselves should never make verifications or assertions. This is part of your test and should always be within the test’s code, never in an page object. The page object will contain the representation of the page, and the services the page provides via methods but no code related to what is being tested should be within the page object.

There is one, single, verification which can, and should, be within the page object and that is to verify that the page, and possibly critical elements on the page, were loaded correctly. This verification should be done while instantiating the page object. In the examples above, both the SignInPage and HomePage constructors check that the expected page is available and ready for requests from the test.

The page object should return things like product name, product price, currently selected quantity, and so on. The test code would then assert that the returned string matches what is expected.

assert_message() would become getMessage() and return the message as a String. See below.

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

(NOTE: read on for why I've changed the PageFactory element to a locator here.)

and then in your test code, you would have

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

Now you've kept the assert code in your test script and out of the page object.

Looking at your code, I would make some further recommendations.

  1. I would suggest you read up on some Java naming conventions. There are a number of sites that have recommendations and I think there are a lot of similarities between them but here's the oracle recommendations to start with. Your method names should be

    verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.

    So assert_message() would turn into assertMessage() and so on. The _s make it look more like python.

  2. Order of preference for locators: ID, CSS selector, and in rare circumstances, XPath. ID should always be your first choice because it (by W3C definition) should be unique on the page. CSS selector should be next because it's the fastest (in my testing faster than ID), has the best browser support, and is most consistently implemented across browsers. XPath should be reserved only for things that cannot be done by CSS seletors like finding an element by contained text. XPath locators are poor performers compared to CSS selectors and do not have the same level of support as CSS selectors. For example, your XPath locator can easily be converted to a CSS selector, "#message > p".

    Here are some CSS selector references to get you started.

    CSS Selectors reference

    CSS Selector tips

  3. Drop PageFactory. Yes, it seems to make things easier but I think in many situations it causes more problems, like stale element exceptions and the like. Prefer instead to scrape the page as needed. Declare all locators at the top of the class and use them in methods when needed.

    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();
        }
    }
    

I know this is more than you asked but hopefully it's helpful.



来源:https://stackoverflow.com/questions/43017058/selenium-java-pagefactory-design-where-do-i-write-my-assertions-following-pa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!