B2G/QA/Automation/Style Guide: Difference between revisions

Jump to navigation Jump to search
→‎Use of Libraries: remove content
(→‎Use of Libraries: remove content)
Line 13: Line 13:


= Use of Libraries =
= Use of Libraries =
== Limited use of conditionals ==
* Methods should not contain logic that depends on properties of the page. The logic and expectations should be within the test, and adding this to the page object could guard your tests against genuine failures.
<source lang="python">
# Good
def click_login(self)
    self.selenium.find_element(*self._login_locator).click()
# Bad
def click_login(self)
    if not self.is_user_logged_in:
        self.selenium.find_element(*self._login_locator).click()
    else:
        pass
</source>
== Locators ==
TBD - jlorenzo
* Locator variables should be prefixed with <code>_</code> to show that it is [http://docs.python.org/tutorial/classes.html#private-variables private].
* Variables should be descriptive of the area and not clash with any properties.
* Should have a suffix of <code>_locator</code>.
* Accessing locators should be done through a property or method as this keeps the locator as read-only.
<source lang="python">
@property
def search_term(self):
    return self.selenium.find_element(*self._search_box_locator).value
</source>
* We should use locators in the following order of preference (there will be exceptions):
** ID
** Name
** Class name
** CSS selector
** XPath
* CSS locators should use whitespace for readability when using direct descendants.
<source lang="python">
# Good
_my_locator = "css=#content > p > a"
   
# Bad
_my_locator = "css=#content>p>a"
</source>
* Use Python tuples to define locators:
<source lang="python">
# Good
_my_locator = (By.ID, "content")
</source>
== PageRegions ==
TBD - jlorenzo
* How to deal with stale root_elements
In some circumstances, for example where a header/navigation is common across the website, we will use a page region. The page region is a child class of the base Page object, which is inherited by all page objects. This means that the navigation can be reached from any page object and herein lies the DRY!
A brief example:
<source lang="python">
class BasePage(Page):
    @property
    def header(self):
        return BasePage.HeaderRegion(self.testsetup)
   
    class HeaderRegion(Page):
        _login_link = (By.ID, "home")
        @def click_login(self):
            self.selenium.find_element(*self._login_link).click()
</source>
Referring to this page region with a property makes it very readable and concise from within the test. Clicking login during a test would be performed like this:
<source lang="python">
my_page.header.click_login()
</source>
Another example where this might be used is on a search results page, the page region being the search results element.
== Assertions ==
TBD - jlorenzo
* Tests should handle the asserts -- not the page objects.
* Tests should use Python's native [https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement assert] statement.
* When doing equivalency assertions, put the expected value first, followed by the actual value, for example:
<source lang="python">
# Good
a = some_function()
assert 'expected result' == a
# Bad
a = some_function()
assert a == 'expected result'
</source>
== How to use GaiaHeader and GaiaBinaryControl ==
TBD - jlorenzo


= Submitting and Reviewing Patches =
= Submitting and Reviewing Patches =
352

edits

Navigation menu