Bug 1238733 - Remove dependency on Marionette harness in firefox-puppeteer; r?whimboo draft
authorMaja Frydrychowicz <mjzffr@gmail.com>
Thu, 17 Mar 2016 23:17:49 -0400
changeset 342698 47b7d64d0a6c36492281930bb80a8dc4a1099bd9
parent 342671 f14898695ee0dd14615914f3e1401f17df57fdd7
child 342699 d74088f597d091735879019365dad4f38587c914
push id13443
push usermjzffr@gmail.com
push dateSun, 20 Mar 2016 22:51:28 +0000
reviewerswhimboo
bugs1238733
milestone48.0a1
Bug 1238733 - Remove dependency on Marionette harness in firefox-puppeteer; r?whimboo BaseFirefoxTestCase inherits from unittest.TestCase and takes advantage of super() to serve as a cooperative base class for children of MarionetteTestCase. MozReview-Commit-ID: 4gsKztEOFrt
testing/puppeteer/firefox/firefox_puppeteer/__init__.py
testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
testing/puppeteer/firefox/requirements.txt
--- a/testing/puppeteer/firefox/firefox_puppeteer/__init__.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/__init__.py
@@ -4,37 +4,37 @@
 
 import os
 
 from marionette_driver.marionette import HTMLElement
 
 from decorators import use_class_as_property
 
 
-__version__ = '3.2.0'
+__version__ = '4.0.0'
 
 
 class Puppeteer(object):
     """The puppeteer class is used to expose libraries to test cases.
 
+    example:
+    `class MyTestCase(MarionetteTestCase, Puppeteer)`
+
     Each library can be referenced by its puppeteer name as a member of a
-    FirefoxTestCase instance. For example, from within a test method, the
+    the TestCase instance. For example, from within a test method, the
     "current_window" member of the "Browser" class can be accessed via
     "self.browser.current_window".
     """
 
     def __init__(self):
         self.marionette = None
 
     def get_marionette(self):
         return self.marionette
 
-    def set_marionette(self, marionette):
-        self.marionette = marionette
-
     @use_class_as_property('api.appinfo.AppInfo')
     def appinfo(self):
         """
         Provides access to members of the appinfo  api.
 
         See the :class:`~api.appinfo.AppInfo` reference.
         """
 
--- a/testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
@@ -1,6 +1,5 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-from firefox_puppeteer.testcases.base import FirefoxTestCase
-from firefox_puppeteer.testcases.update import UpdateTestCase
+from firefox_puppeteer.testcases.base import BaseFirefoxTestCase
--- a/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
@@ -1,26 +1,43 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-from marionette import MarionetteTestCase
+import unittest
 
 from firefox_puppeteer import Puppeteer
 from firefox_puppeteer.ui.browser.window import BrowserWindow
 
 
-class FirefoxTestCase(MarionetteTestCase, Puppeteer):
-    """Base testcase class for Firefox Desktop tests.
+class BaseFirefoxTestCase(unittest.TestCase, Puppeteer):
+    """Base TestCase class for Firefox Desktop tests.
+
+    This is designed to enhance MarionetteTestCase by inserting the Puppeteer
+    mixin class (so Firefox specific API modules are exposed to test scope) and
+    providing common set-up and tear-down code for Firefox tests.
+
+    Child classes are expected to also subclass MarionetteTestCase such that
+    MarionetteTestCase is inserted into the MRO after FirefoxTestCase but before
+    unittest.TestCase.
 
-    It enhances the Marionette testcase by inserting the Puppeteer mixin class,
-    so Firefox specific API modules are exposed to test scope.
+    example:
+    `class AwesomeTestCase(FirefoxTestCase, MarionetteTestCase)`
+
+    The key role of MarionetteTestCase is to set self.marionette appropriately
+    in `__init__`. Any TestCase class that satisfies this requirement is
+    compatible with this class.
+
+    If you're extending the inheritance tree further to make specialized
+    TestCases, favour the use of super() as opposed to explicit calls to a
+    parent class.
+
     """
     def __init__(self, *args, **kwargs):
-        MarionetteTestCase.__init__(self, *args, **kwargs)
+        super(BaseFirefoxTestCase, self).__init__(*args, **kwargs)
 
     def _check_and_fix_leaked_handles(self):
         handle_count = len(self.marionette.window_handles)
 
         try:
             self.assertEqual(handle_count, self._start_handle_count,
                              'A test must not leak window handles. This test started with '
                              '%s open top level browsing contexts, but ended with %s.' %
@@ -58,18 +75,20 @@ class FirefoxTestCase(MarionetteTestCase
 
         # Marionette doesn't keep the former context, so restore to chrome
         self.marionette.set_context('chrome')
 
         # Ensure that we always have a valid browser instance available
         self.browser = self.windows.switch_to(lambda win: type(win) is BrowserWindow)
 
     def setUp(self, *args, **kwargs):
-        MarionetteTestCase.setUp(self, *args, **kwargs)
-        Puppeteer.set_marionette(self, self.marionette)
+        try:
+            super(BaseFirefoxTestCase, self).setUp(*args, **kwargs)
+        except (AttributeError, TypeError):
+            unittest.TestCase.setUp(self)
 
         self._start_handle_count = len(self.marionette.window_handles)
         self.marionette.set_context('chrome')
 
         self.browser = self.windows.current
         self.browser.focus()
         with self.marionette.using_context(self.marionette.CONTEXT_CONTENT):
             # Ensure that we have a default page opened
@@ -81,9 +100,12 @@ class FirefoxTestCase(MarionetteTestCase
         try:
             self.prefs.restore_all_prefs()
 
             # This code should be run after all other tearDown code
             # so that in case of a failure, further tests will not run
             # in a state that is more inconsistent than necessary.
             self._check_and_fix_leaked_handles()
         finally:
-            MarionetteTestCase.tearDown(self, *args, **kwargs)
+            try:
+                super(BaseFirefoxTestCase, self).tearDown(*args, **kwargs)
+            except (AttributeError, TypeError):
+                unittest.TestCase.tearDown(self)
--- a/testing/puppeteer/firefox/requirements.txt
+++ b/testing/puppeteer/firefox/requirements.txt
@@ -1,5 +1,2 @@
-# The following line can be removed once testcases are no longer part of the puppeteer module.
-marionette-client >= 2.2.0
-
 marionette-driver >= 1.3.0
 mozinfo >= 0.8