Confirmed users
211
edits
(Updated example to reflect more Firefox OS) |
|||
Line 63: | Line 63: | ||
== General == | == General == | ||
* All page objects should inherit from <code> | * All page objects should inherit from <code>Page</code> in page.py. | ||
* Page objects should not do asserts. This should be done within the test. | * Page objects should not do asserts. This should be done within the test. | ||
* Each page should be grouped within one module. | * Each page should be grouped within one module. | ||
* If using multiple words to describe a module separate them with underscores '_' | * If using multiple words to describe a module separate them with underscores '_' | ||
* Timeout time should be taken from pytest-mozwebqa via <code>page.py's</code> timeout property. | |||
* Single quotes (') should be used instead of double (") throughout. | * Single quotes (') should be used instead of double (") throughout. | ||
* Methods should have a single purpose. | * Methods should have a single purpose. | ||
Line 75: | Line 76: | ||
<source lang="python"> | <source lang="python"> | ||
# Good | # Good | ||
def | def click_login(self) | ||
self. | self.selenium.find_element(*self._login_locator).click() | ||
# Bad | # Bad | ||
def | def click_login(self) | ||
if not self.is_user_logged_in: | if not self.is_user_logged_in: | ||
self. | self.selenium.find_element(*self._login_locator).click() | ||
else: | else: | ||
pass | pass | ||
Line 140: | Line 141: | ||
<source lang="python"> | <source lang="python"> | ||
class | class BasePage(Page): | ||
@property | @property | ||
def header(self): | def header(self): | ||
return | return BasePage.HeaderRegion(self.testsetup) | ||
class HeaderRegion(Page): | class HeaderRegion(Page): | ||
Line 150: | Line 151: | ||
_login_link = (By.ID, "home") | _login_link = (By.ID, "home") | ||
@def | @def click_login(self): | ||
self. | self.selenium.find_element(*self._login_link).click() | ||
</source> | </source> | ||
Line 164: | Line 165: | ||
* Module names should be called test_ and then behavioral areas. | * Module names should be called test_ and then behavioral areas. | ||
test_search.py | test_search.py | ||
* Test method signature should include mozwebqa to use pytest-mozwebqa plugin. | |||
<source lang="python"> | |||
def test_example(self, mozwebqa): | |||
</source> | |||
* Test method names should always show the intent of the test case. | * Test method names should always show the intent of the test case. | ||
Line 169: | Line 175: | ||
<source lang="python"> | <source lang="python"> | ||
# Good | # Good | ||
def test_that_advanced_search_does_not_find_item(self): | def test_that_advanced_search_does_not_find_item(self, mozwebqa): | ||
# Bad | # Bad | ||
def test_advanced_search(self): | def test_advanced_search(self, mozwebqa): | ||
</source> | </source> | ||
Line 178: | Line 184: | ||
* Tests should handle the asserts -- not the page objects. | * Tests should handle the asserts -- not the page objects. | ||
* Tests should use | * Tests should use Python's native [https://docs.python.org/2/reference/simple_stmts.html#the-assert-statement assert] statement. | ||
** Note that this is a change from our previous standard of using the [https://wiki.mozilla.org/Web_Testing/Automation/UnittestZero UnittestZero] package. | |||
* When doing equivalency assertions, put the expected value first, followed by the actual value, for example: | |||
<source lang="python"> | |||
assert 'expected' == 'actual' # good | |||
assert 'actual' == 'expected' # bad | |||
</source> | |||
* When doing negative equivalency, use != and put the unexpected value first, followed by the actual value, for example: | |||
<source lang="python"> | |||
assert 'unexpected' != 'actual' # good | |||
assert 'actual' != 'unexpected' # bad | |||
</source> | |||
* To directly cause a test to fail raise an AssertionError with an appropriate message, for example: | |||
<source lang="python"> | |||
raise AssertionError('message') | |||
</source> | |||
* See [http://pytest.org/latest/assert.html pytest's documentation on asserts] for more help. | |||
= Size of patches = | = Size of patches = | ||
To make sure that we can review your patch as quickly and efficiently as possibly we would like patches to have a single test in them and the necessary changes to the page objects. This also limits the chances of merge conflicts later. | To make sure that we can review your patch as quickly and efficiently as possibly we would like patches to have a single test in them and the necessary changes to the page objects. This also limits the chances of merge conflicts later. | ||
== Using new and old standards together == | |||
As we (and Selenium and automation) develop more knowledge some projects might fall behind the standards in this style guide. It can be tempting to want to fix all of the outdated style but in order to keep patches/pulls small (see above!) we are happy to have new and old standards of code sit side by side. As we regularly review and update tests the project will be brought completely up to our current standards. | |||
Or if you prefer, log a GitHub issue to have a section of code addressed separately to the job you are doing. |