QA/Execution/Web Testing/Docs/Automation/StyleGuide: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 4: Line 4:
==File headers==
==File headers==


*At the top of each file should have python file header
*At the top of each file should have python file header
 
<pre class="brush:py;toolbar:false;">
     #!/usr/bin/env python
     #!/usr/bin/env python
</pre>


*Each file should have a copy of the [http://www.mozilla.org/MPL/boilerplate-1.1/mpl-tri-license-sh MPL]
*Each file should have a copy of the [http://www.mozilla.org/MPL/boilerplate-1.1/mpl-tri-license-sh MPL]


*Each file should pass [http://www.python.org/dev/peps/pep-0008/ PEP8] except for line length, see below.   
*Each file should pass [http://www.python.org/dev/peps/pep-0008/ PEP8] except for line length, see below.   
** I.e. parameters  should have a comma and a space e.g.
** I.e. parameters  should have a comma and a space e.g.
    Good: def method(self, parameter)
 
<pre class="brush:py;toolbar:false;">
    Bad:  def method(self,parameter), etc
    # Good
    def method(self, parameter)  


    # Bad
    def method(self,parameter)
</pre>
      
      


Line 25: Line 32:
**Class names should be in Pascal style as this is Python idiomatic
**Class names should be in Pascal style as this is Python idiomatic


     Good: class TestThisSite(unittest.TestCase):
<pre class="brush:py;toolbar:false;">
     Badclass test_this_site(unittest.TestCase):
     # Good
    class TestThisSite(unittest.TestCase):
      
    # Bad
    class test_this_site(unittest.TestCase):
</pre>


==Page Object Style Guide==
==Page Object Style Guide==
Line 44: Line 56:
*Accessing Locator Variables
*Accessing Locator Variables
**Accessing Locators should be done through a property method as this keeps the locator as readonly.
**Accessing Locators should be done through a property method as this keeps the locator as readonly.
 
 
<pre class="brush:py;toolbar:false;">
     @property
     @property
     def search_box(self):
     def search_box(self):
         return self.search_box_locator
         return self.search_box_locator
       
</pre>
 
*This approach can also be used with get_* calls with Selenium making it more idiomatic for the call.
*This approach can also be used with get_* calls with Selenium making it more idiomatic for the call.


<pre class="brush:py;toolbar:false;">
     @property
     @property
     def page_title(self):
     def page_title(self):
         return self.selenium.get_title()
         return self.selenium.get_title()
</pre>


*Action methods
*Action methods
**Methods that perform actions on the page should indicate the action in the method name
**Methods that perform actions on the page should indicate the action in the method name


     GOOD: def click_report_with_length(length)
<pre class="brush:py;toolbar:false;">
     BAD: def report_length(length)
    # Good
     def click_report_with_length(length)
 
    # Bad
     def report_length(length)
</pre>


==Test Style Guide==
==Test Style Guide==
Line 68: Line 89:


*Test Case names should always show the intent of the test case.
*Test Case names should always show the intent of the test case.
**GOOD: def test_that_advanced_search_doesnt_find_item(self):
 
**BAD: def test_advanced_search(self):
<pre class="brush:py;toolbar:false;">
    # Good
    def test_that_advanced_search_doesnt_find_item(self):
 
    # Bad
    def test_advanced_search(self):
</pre>
 
**CAVEAT: setUp and tearDown are exceptions to the rule as they are needed for unittest
**CAVEAT: setUp and tearDown are exceptions to the rule as they are needed for unittest


Line 76: Line 104:
*Every Test module will have an main() function caller
*Every Test module will have an main() function caller


<pre class="brush:py;toolbar:false;">
         if __name__ == "__main__":
         if __name__ == "__main__":
             unittest.main()
             unittest.main()
</pre>

Revision as of 16:14, 9 December 2010

The goal of the style guide is to try provide rules to write code that looks the same no matter what project. It is a guide and is always up for discussion by the team. I have created templates based on the details below.

All Files

File headers

  • At the top of each file should have python file header
    #!/usr/bin/env python
  • Each file should have a copy of the MPL
  • Each file should pass PEP8 except for line length, see below.
    • I.e. parameters should have a comma and a space e.g.
    # Good
    def method(self, parameter) 

    # Bad
    def method(self,parameter)


    • Lines should try not to have more than 100 characters. This allows 2 files to be side by side with no overlap for easier development.(I base this on MacVim on my MBP)
    • Indenting should be a soft tab(4 spaces) as common with in Python. Do not mix tabs and spaces
    • There should be no whitespace at the end of the file(as per PEP8)
    • Comments should be on the line above. Remember to update comments when changing code so that code matches the comments.
    • Class names should be in Pascal style as this is Python idiomatic
    # Good
    class TestThisSite(unittest.TestCase):
    
    # Bad
    class test_this_site(unittest.TestCase):

Page Object Style Guide

  • All Page Objects should inherit from Page in page.py
  • Page Objects should not do asserts. This should be done within the test
  • Each Page should be grouped within one module
  • If using mutliple words to describe a module separate them with underscores '_'
   test_search.py
  • timeout time should be taken from vars.py
  • Locators Class Variables
    • Locator variables should be prefixed with _ to show that it is "private"
    • Variables should be descriptive of the area and not clash with any properties
    • Suffix of _locator
  • Accessing Locator Variables
    • Accessing Locators should be done through a property method as this keeps the locator as readonly.
    @property
    def search_box(self):
        return self.search_box_locator
  • This approach can also be used with get_* calls with Selenium making it more idiomatic for the call.
    @property
    def page_title(self):
        return self.selenium.get_title()
  • Action methods
    • Methods that perform actions on the page should indicate the action in the method name
    # Good
    def click_report_with_length(length)

    # Bad
    def report_length(length)

Test Style Guide

  • Module names should be called test_ and then behavioural areas. E.g. test_search_positive.py
  • Test setup should read in details from vars.py
  • Test Case names should always show the intent of the test case.
    # Good
    def test_that_advanced_search_doesnt_find_item(self):

    # Bad
    def test_advanced_search(self):
    • CAVEAT: setUp and tearDown are exceptions to the rule as they are needed for unittest
  • Tests should handle the asserts not the Page objects
  • Every Test module will have an main() function caller
        if __name__ == "__main__":
            unittest.main()