Part 8: Using a base class

by 3 contributors:

Now you have multiple tests you are probably feeling pretty good about your progress. However there are other ways to improve code efficiency further — you may notice that you've so far had to include a setUp() and a tearDown() method in each test file, going by the current constructs we've seen in this series. If you have several dozen tests then that’s a lot of code duplication! In this article we'll look at how to put the setUp()/tearDown() code common to all tests into a TestBase class, which can then be imported into each individual test file.

test_base.py

To start with, create a new file called test_base.py, in the same directory as your existing test cases.

Next, move your important statements that relate to the common setup (unittest, Marionette and time) into the file, along with a TestBase class containing the setUp() and tearDown() methods, and associated common helper functions (such as unlock_screen()). The file should look something like this:

import time
import unittest
from marionette import Marionette


class TestBase(unittest.TestCase):

    def unlock_screen(self):
        self.marionette.execute_script('window.wrappedJSObject.lockScreen.unlock();')

    def kill_all(self):
        self.marionette.switch_to_frame()
        self.marionette.execute_async_script("""
             // Kills all running apps, except the homescreen.
             function killAll() {
               let manager = window.wrappedJSObject.AppWindowManager;

               let apps = manager.getApps();
               for (let id in apps) {
                 let origin = apps[id].origin;
                 if (origin.indexOf('verticalhome') == -1) {
                   manager.kill(origin);
                 }
               }
             };
             killAll();
             // return true so execute_async_script knows the script is complete
             marionetteScriptFinished(true);
            """)

    def setUp(self):
         # Create the client for this session. Assuming you're using the default port on a Marionette instance running locally
        self.marionette = Marionette()
        self.marionette.start_session()

        # Unlock the screen
        self.unlock_screen()

        # kill all open apps
        self.kill_all()

        # Switch context to the homescreen iframe and tap on the contacts icon
        time.sleep(2)
        home_frame = self.marionette.find_element('css selector', 'div.homescreen iframe')
        self.marionette.switch_to_frame(home_frame)


    def tearDown(self):
        # Close the Marionette session now that the test is finished
        self.marionette.delete_session()

Updating your test files

With your test_base.py file created, you need to import TestBase into your test files, and the test classes need to be changed to extend the TestBase class:

import unittest
from marionette import Wait
from marionette import By
from test_base import TestBase
 
class TestContacts(TestBase):

    def test(self):
        # Tests in here
 
if __name__ == '__main__':
    unittest.main()

Try running your test file again.

It may not look like much now but when you have dozens or hundreds of tests this really saves a lot of duplicate code.

Document Tags and Contributors

Contributors to this page: chrisdavidmills, zac_c, Tingyu
Last updated by: chrisdavidmills,
Hide Sidebar