Exemplo n.º 1
0
class TestXpathBrowser(unittest.TestCase):
    def setUp(self):
        # We need to enter "single test level" of life for each test
        # It will initialize the webdriver if no webdriver is present from upper levels
        self._level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
        # Get Xpath browser
        self.browser = self._level_mngr.get_xpathbrowser(name=__name__)

    def tearDown(self):
        # Make sure we quit those webdrivers created in this specific level of life
        self._level_mngr.exit_level()

    def test_select(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath('//div') # Xpath must be present, but no inner element may be returned
        self.browser.select_xsingle('//div') # Xpath must be present and at least 1 element must be present
        
    def test_extract(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath('//div') # Xpath must be present, but no inner element may be returned
        self.browser.extract_xsingle('//div') # Xpath must be present and at least 1 element must be present        

    def get_local_page(self, file_name):
        # Auxiliary method
        root_dir = os.path.abspath(os.path.dirname(__file__))
        url = 'file://' + os.path.join(root_dir, 'html', file_name)
        self.browser.get_url(url)
Exemplo n.º 2
0
 def setUp(self):
     # We need to enter "single test level" of life for each test
     # It will initialize the webdriver if no webdriver is present from upper levels
     self.__level_mngr = WebdriverManager().enter_level(
         level=SINGLE_TEST_LIFE)
     # Get Xpath browser
     self.browser = self.__level_mngr.get_xpathbrowser(name=__name__)
Exemplo n.º 3
0
class XpathShell(object):
    def __init__(self, logger=None):
        self.log = logger or Logger('Xpath Shell')

    def get(self, url):
        u = urlparse.urlparse(url)
        if not u.scheme:
            u = ('http', u.netloc, u.path, u.params, u.query, u.fragment)
            url = urlparse.urlunparse(u)
        self.browser.get_url(url)
        self.log.i('Current url: %r' % self.browser.current_url())

    def run_shell(self, url=None):
        self.level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
        browser = self.browser = self.level_mngr.get_xpathbrowser(name='Browser')
        #Aliases #TODO: add ipython extension
        ex  = extract = browser.extract_xpath
        exs = xsingle = browser.extract_xsingle
        get = self.get
        def reset_browser():
            self.level_mngr.exit_level()
            self.level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
        if url:
            self.get(url)
        print('Available objects/commands %s' % sorted(locals()))
        IpythonEmbedder().embed()
        self.level_mngr.exit_level()
        WebdriverManager().stop_display()
Exemplo n.º 4
0
class WebUnitTestBase(unittest.TestCase):
    def _path_to_url(self, path):
        return "file://" + path

    def get_local_page(self, path):
        self.browser.get_url(self._path_to_url(path))

    @contextmanager
    def create_html(self, name, body, **kwargs):
        templ = """
<!DOCTYPE html>
<html>
<head>
  hotexamples_com
  <title>{name}</title>
</head>
<body>
      {body}
</body>
</html>
        """
        jquery = ""
        kwargs.update(locals())
        html = templ.format(**kwargs)
        if not self._tempdir:
            self._tempdir = tempfile.mkdtemp(prefix="smoothtest")
        path = os.path.join(self._tempdir, name + ".html")
        # Create html page in temporary dir
        with open(path, "w") as fh:
            fh.write(html)
        try:
            yield path
        except:
            raise
        finally:
            os.remove(path)

    def setUp(self):
        self.__level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
        webdriver = self.__level_mngr.acquire_driver()
        logger = Logger(__name__)
        self.browser = XpathBrowser("", webdriver, logger, settings={})
        # Temp dir to save pages
        self._tempdir = None

    def tearDown(self):
        self.__level_mngr.exit_level()
        if self._tempdir:
            shutil.rmtree(self._tempdir, ignore_errors=True)
            self._tempdir = None
Exemplo n.º 5
0
class WebUnitTestBase(unittest.TestCase):
    def _get_local_html_path(self, name):
        return os.path.join(os.path.dirname(__file__), 'html', name)

    def _local_path_to_url(self, path):
        return 'file://' + path

    def get_local_page(self, path):
        self.browser.get_url(self._local_path_to_url(path))

    @contextmanager
    def create_html(self, name, body, jquery=True, **kwargs):
        templ = '''
<!DOCTYPE html>
<html>
<head>
  hotexamples_com
  <title>{name}</title>
</head>
<body>
      {body}
</body>
</html>
        '''
        if jquery:
            jquery = ''
        else:
            jquery = ''

        kwargs.update(locals())
        html = templ.format(**kwargs)
        path = self._get_local_html_path(name + '.html')
        with open(path, 'w') as fh:
            fh.write(html)
        try:
            yield path
        except:
            raise
        finally:
            os.remove(path)

    def setUp(self):
        self.__level_mngr = WebdriverManager().enter_level(
            level=SINGLE_TEST_LIFE)
        webdriver = self.__level_mngr.acquire_driver()
        logger = Logger(__name__)
        self.browser = XpathBrowser('', webdriver, logger, settings={})

    def tearDown(self):
        self.__level_mngr.exit_level()
Exemplo n.º 6
0
class TestXpathBrowser(unittest.TestCase):
    def setUp(self):
        # We need to enter "single test level" of life for each test
        # It will initialize the webdriver if no webdriver is present from upper levels
        self.__level_mngr = WebdriverManager().enter_level(
            level=SINGLE_TEST_LIFE)
        # Get Xpath browser
        self.browser = self.__level_mngr.get_xpathbrowser(name=__name__)
        # Line above is equivalent to doing:
        #    from smoothtest.Logger import Logger
        #    from smoothtest.webunittest.XpathBrowser import XpathBrowser
        #    # Once we make sure there is a webdriver available, we acquire it
        #    # and block usage from other possible users
        #    webdriver = self.__level_mngr.acquire_driver()
        #    # Initialize the XpathBrowser class
        #    logger = Logger(__name__)
        #    self.browser = XpathBrowser('', webdriver, logger, settings={})

    def tearDown(self):
        # Make sure we quit those webdrivers created in this specific level of life
        self.__level_mngr.exit_level()

    def test_select(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath(
            '//div'
        )  # Xpath must be present, but no inner element may be returned
        self.browser.select_xsingle(
            '//div'
        )  # Xpath must be present and at least 1 element must be present

    def test_extract(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath(
            '//div'
        )  # Xpath must be present, but no inner element may be returned
        self.browser.extract_xsingle(
            '//div'
        )  # Xpath must be present and at least 1 element must be present

    def get_local_page(self, file_name):
        # Auxiliary method
        root_dir = os.path.abspath(os.path.dirname(__file__))
        url = 'file://' + os.path.join(root_dir, 'html', file_name)
        self.browser.get_url(url)
Exemplo n.º 7
0
 def __init__(self):
     '''
     Initialize attributes
     '''
     self._timeout = 1
     self._ishell = None  # Ipython Shell instance
     self.test_config = {
     }  # Configuration parameters sent for each test round
     self._slave = None  # Slave instance (configures how tests are ran)
     self._child_pids = [
     ]  # Store pids of children, in case we need to kill them
     self._wdriver_mngr = WebdriverManager(
     )  # common WebdriverManager instance
     self._browser_name = None  # Current selected browser name
     self._level_mngr = None  # WebdriverLevelManager for each time we enter/leave a "webdriver life level"
Exemplo n.º 8
0
class TestChat(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        # It will initialize the webdriver if no webdriver is present from upper levels
        # Since we don't want to initialize a webdriver for each single test
        # we create the webdriver one level upper SINGLE_TEST_LIFE
        cls.cls_level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)

    @classmethod
    def tearDownClass(cls):
        cls.cls_level_mngr.exit_level()

    def setUp(self):
        # The webdriver is already initialized on previous level
        # We simply manage it's context with this new _level_mngr
        self._level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
        # Lock webdriver and build XpathBrowser API
        self.browser = self._level_mngr.get_xpathbrowser(name=__name__)
        self.browser.set_base_url(base_url)

    def tearDown(self):
        # Release webdriver, we are not longer using it.
        self._level_mngr.exit_level()

    def test_loaded(self):
        b = self.browser
        b.get_page('/')
        # Make sure there is at least 1 element
        b.select_xsingle(".//*[@id='input_area']")

    def test_send_msg(self):
        browser1 = self.browser
        path = '/'
        with WebdriverManager().enter_level(level=SINGLE_TEST_LIFE, name='Browser2') \
        as browser2:
            browser1.get_page(path)
            browser2.set_base_url(base_url)
            browser2.get_page(path)
            username = '******'
            message = 'my message'
            browser1.fill_input(".//*[@id='username']", username)
            browser1.fill_input(".//*[@id='message']", message)
            browser1.click(".//*[@id='input_area']/button")
            msgs_xpath = ".//*[@id='chat']/div"
            msg_recv = browser1.extract_xpath(msgs_xpath)[-1]
            self.assertEqual(msg_recv, '%s: %s' % (username, message))
            msg_recv2 = browser2.extract_xpath(msgs_xpath)[-1]
            self.assertEqual(msg_recv, msg_recv2)
Exemplo n.º 9
0
 def setUpClass(cls):
     # We need to enter "single test level" of life for each test
     # It will initialize the webdriver if no webdriver is present from upper levels
     cls._level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)
     # Get Xpath browser
     cls.browser = cls._level_mngr.get_xpathbrowser(name=__name__)
     cls.browser.set_base_url(base_url)
Exemplo n.º 10
0
def smoke_test_module():
    from smoothtest.webunittest.WebdriverManager import WebdriverManager
    mngr = WebdriverManager()
    #    mngr.setup_display()
    #    webdriver = mngr.new_webdriver()
    u = u'https://www.google.cl/?gfe_rd=cr&ei=ix0kVfH8M9PgwASPoIFo&gws_rd=ssl'
    print WebdriverUtils.Url(u).get_path_and_on()
Exemplo n.º 11
0
 def setUp(self):
     # The webdriver is already initialized on previous level
     # We simply manage it's context with this new _level_mngr
     self._level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
     # Lock webdriver and build XpathBrowser API
     self.browser = self._level_mngr.get_xpathbrowser(name=__name__)
     self.browser.set_base_url(base_url)
Exemplo n.º 12
0
 def setUp(self):
     self.__level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
     webdriver = self.__level_mngr.acquire_driver()
     logger = Logger(__name__)
     self.browser = XpathBrowser("", webdriver, logger, settings={})
     # Temp dir to save pages
     self._tempdir = None
Exemplo n.º 13
0
 def test(self, test_paths, argv=[], smoke=False):
     '''
     :param test_paths: iterable like ['package.module.test_class.test_method', ...]
     '''
     results = TestResults()
     if smoke or not test_paths:
         self.log.i('Ignoring %r \n  (smoke mode or no tests found)' %
                    list(test_paths))
         return results
     level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)
     for tpath in test_paths:
         class_ = self._import_test(tpath)
         if isinstance(class_, TestException):
             results.append_result(tpath, class_)
         else:
             result = self._run_test(tpath, argv, class_)
             results.append_result(tpath, result)
     level_mngr.exit_level()
     return results
Exemplo n.º 14
0
 def test(self, test_paths, argv=[], smoke=False):
     '''
     :param test_paths: iterable like ['package.module.test_class.test_method', ...]
     '''
     results = TestResults()
     if smoke or not test_paths:
         self.log.i('Ignoring %r \n  (smoke mode or no tests found)' %
                    list(test_paths))
         return results
     level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)
     for tpath in test_paths:
         class_ = self._import_test(tpath)
         if isinstance(class_, TestException):
             results.append_result(tpath, class_)
         else:
             result = self._run_test(tpath, argv, class_)
             results.append_result(tpath, result)
     level_mngr.exit_level()
     return results
Exemplo n.º 15
0
class SearchEnginesDemo(unittest.TestCase):
    def setUp(self):
        # We need to enter "single test level" of life for each test
        # It will initialize the webdriver if no webdriver is present from upper levels
        self._level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
        # Get Xpath browser
        self.browser = self._level_mngr.get_xpathbrowser(name=__name__)

    def tearDown(self):
        # Make sure we quit those webdrivers created in this specific level of life
        self._level_mngr.exit_level()

    def test_duckduckgo(self):
        # Load a local page for the demo
        self.browser.get_url('https://duckduckgo.com/')
        # Type smoothtest and press enter
        self.browser.fill(".//*[@id='search_form_input_homepage']", 'smoothtest\n')
        result_link = './/a[@title="smoothtest "]'
        # Wait for the result to be available
        self.browser.wait_condition(lambda brw: brw.select_xpath(result_link))
        # Click on result
        self.browser.click(result_link)
        # First result should point to github
        expected_url = 'https://github.com/joaduo/smoothtest'
        wait_url = lambda brw: brw.current_url() == expected_url
        # Make sure we end up in the right url
        self.assertTrue(self.browser.wait_condition(wait_url))

    def test_google(self):
        # go to google
        self.browser.get_url('https://www.google.com/')
        # search for smoothtest and press enter
        self.browser.fill(".//*[@id='lst-ib']", 'smoothtest\n')
        first_result = './/a[contains(text(),"smoothtest 0.1.3")]'
        # Wait for first result
        self.browser.wait_condition(lambda brw: brw.select_xpath(first_result))
        # Click first result
        self.browser.click(first_result)
        # Make sure we went to pypi
        wait_pypi_url = lambda brw: brw.current_url() == 'https://pypi.python.org/pypi/smoothtest/0.1.3'
        self.assertTrue(self.browser.wait_condition(wait_pypi_url))
Exemplo n.º 16
0
 def __init__(self):
     '''
     Initialize attributes
     '''
     self._timeout = 1
     self._ishell = None   # Ipython Shell instance
     self.test_config = {} # Configuration parameters sent for each test round
     self._slave = None    # Slave instance (configures how tests are ran)
     self._child_pids = [] # Store pids of children, in case we need to kill them
     self._wdriver_mngr = WebdriverManager() # common WebdriverManager instance
     self._browser_name = None # Current selected browser name
     self._level_mngr = None # WebdriverLevelManager for each time we enter/leave a "webdriver life level" 
Exemplo n.º 17
0
def smoke_test_module():
    from smoothtest.webunittest.WebdriverManager import WebdriverManager
    from smoothtest.settings.default import SINGLE_TEST_LIFE
    mngr = WebdriverManager()
    mngr.set_browser('Firefox')
    lvl = mngr.enter_level(level=SINGLE_TEST_LIFE)
    class ExampleTest(object):
        def test_something(self):
            raise LookupError('Example Exception')
    test = ExampleTest()
    browser = lvl.get_xpathbrowser(name='test')
    get_browser = lambda : browser
    dec = ScreenshotDecorator(get_browser, test)
    dec._decorate_exc_sshot()
    lvl.get_locked_driver().get('http://www.example.com')
    try:
        test.test_something()
    except Exception as e:
        pass
        #print e
    lvl.exit_level()
Exemplo n.º 18
0
class TestXpathBrowser(unittest.TestCase):
    def setUp(self):
        # We need to enter "single test level" of life for each test
        # It will initialize the webdriver if no webdriver is present from upper levels
        self.__level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
        # Get Xpath browser
        self.browser = self.__level_mngr.get_xpathbrowser(name=__name__)
        # Line above is equivalent to doing:
        #    from smoothtest.Logger import Logger
        #    from smoothtest.webunittest.XpathBrowser import XpathBrowser
        #    # Once we make sure there is a webdriver available, we acquire it
        #    # and block usage from other possible users
        #    webdriver = self.__level_mngr.acquire_driver()
        #    # Initialize the XpathBrowser class
        #    logger = Logger(__name__)
        #    self.browser = XpathBrowser('', webdriver, logger, settings={})

    def tearDown(self):
        # Make sure we quit those webdrivers created in this specific level of life
        self.__level_mngr.exit_level()

    def test_select(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath('//div') # Xpath must be present, but no inner element may be returned
        self.browser.select_xsingle('//div') # Xpath must be present and at least 1 element must be present
        
    def test_extract(self):
        # Load a local page for the demo
        self.get_local_page('xpath_browser_demo.html')
        # Do 2 type of selection
        self.browser.select_xpath('//div') # Xpath must be present, but no inner element may be returned
        self.browser.extract_xsingle('//div') # Xpath must be present and at least 1 element must be present        

    def get_local_page(self, file_name):
        # Auxiliary method
        root_dir = os.path.abspath(os.path.dirname(__file__))
        url = 'file://' + os.path.join(root_dir, 'html', file_name)
        self.browser.get_url(url)
Exemplo n.º 19
0
def smoke_test_module():
    from smoothtest.webunittest.WebdriverManager import WebdriverManager
    from smoothtest.settings.default import SINGLE_TEST_LIFE
    mngr = WebdriverManager()
    mngr.set_browser('Firefox')
    lvl = mngr.enter_level(level=SINGLE_TEST_LIFE)

    class ExampleTest(object):
        def test_something(self):
            raise LookupError('Example Exception')

    test = ExampleTest()
    browser = lvl.get_xpathbrowser(name='test')
    get_browser = lambda: browser
    dec = ScreenshotDecorator(get_browser, test)
    dec._decorate_exc_sshot()
    lvl.get_locked_driver().get('http://www.example.com')
    try:
        test.test_something()
    except Exception as e:
        pass
        #print e
    lvl.exit_level()
Exemplo n.º 20
0
 def run_shell(self, url=None):
     self.level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
     browser = self.browser = self.level_mngr.get_xpathbrowser(name='Browser')
     #Aliases #TODO: add ipython extension
     ex  = extract = browser.extract_xpath
     exs = xsingle = browser.extract_xsingle
     get = self.get
     def reset_browser():
         self.level_mngr.exit_level()
         self.level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
     if url:
         self.get(url)
     print('Available objects/commands %s' % sorted(locals()))
     IpythonEmbedder().embed()
     self.level_mngr.exit_level()
     WebdriverManager().stop_display()
Exemplo n.º 21
0
 def run_shell(self, url=None):
     level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
     browser = self.browser = level_mngr.get_xpathbrowser(name='Browser')
     #Aliases #TODO: add ipython extension
     ex  = extract = browser.extract_xpath
     exs = xsingle = browser.extract_xsingle
     get = self.get
     if url:
         self.get(url)
     IpythonEmbedder().embed()
     level_mngr.exit_level()
     WebdriverManager().stop_display()
Exemplo n.º 22
0
 def reset_browser():
     self.level_mngr.exit_level()
     self.level_mngr = WebdriverManager().enter_level(level=PROCESS_LIFE)
Exemplo n.º 23
0
 def stop_display(self):
     '''
     Stop display if there is a virtual screen running
     '''
     WebdriverManager().stop_display()
Exemplo n.º 24
0
class Main(ParentBase):
    '''
    This class contains the "main loop" logic of the autotest command
    It will create 2 forked subprocess as:
        Main Process (this one)
          Master Subprocess (Child)
            TestRunner Subprocess (Grand Child)

    Roles are as:
        Main: where the CLI loop is done, sending commands to Master.
        Master: where file watching happens; events from Main and TestRunner are integrated
            decides whether to: trigger tests, kill TestRunner and recreate it.
        TestRunner: where tests are loaded and ran, test results are sent back to Master.
    '''
    def __init__(self):
        '''
        Initialize attributes
        '''
        self._timeout = 1
        self._ishell = None  # Ipython Shell instance
        self.test_config = {
        }  # Configuration parameters sent for each test round
        self._slave = None  # Slave instance (configures how tests are ran)
        self._child_pids = [
        ]  # Store pids of children, in case we need to kill them
        self._wdriver_mngr = WebdriverManager(
        )  # common WebdriverManager instance
        self._browser_name = None  # Current selected browser name
        self._level_mngr = None  # WebdriverLevelManager for each time we enter/leave a "webdriver life level"

    def run(self, test_config, embed_ipython=False, block=False):
        '''
        Runs the main CLI loop.
        If ipython is not present it will fallback to gdb as CLI.

        :param test_config: initial configuration parameters
        :param embed_ipython: if True, it will embed a interactive shell.
        :param block: block waiting for events (in case no shell was enabled)
        '''
        self.log.set_pre_post(pre='Autotest CLI')
        self.test_config = test_config
        self.create_child()
        if embed_ipython:
            from .ipython_extension import load_extension

            def extension(ipython):
                return load_extension(ipython, self)

            self._ishell = IpythonEmbedder().embed(extension)
            self.kill_child()
            self.end_main()
            self._wdriver_mngr.stop_display()
            raise SystemExit(0)
        elif block:
            self.log.i(self.recv())

    def create_child(self):
        '''
        Create Master role subprocess
        '''
        slave = self._build_slave()

        def callback(conn):
            if self._ishell:
                self._ishell.exit_now = True
            sys.stdin.close()
            master = Master(conn, slave)
            poll = master.io_loop(self.test_config)
            while True:
                poll.next()

        self.start_subprocess(callback, pre='Master')
        slave_pid = self.call_remote(Master.get_subprocess_pid)
        self._child_pids.append(('slave_pid', slave_pid))
        self._child_pids.append(('master_pid', self.get_subprocess_pid()))

    def _build_slave(self):
        # Build the Slave class instance (used to control how tests are ran)
        if not self._slave:
            # Release no longer used webdriver
            if self._level_mngr:
                self._level_mngr.release_driver()
            # Quit those drivers not responding
            self._wdriver_mngr.quit_all_failed_webdrivers()
            self._wdriver_mngr.set_browser(self._get_browser_name())
            # Enter the level again
            self._level_mngr = self._wdriver_mngr.enter_level(
                level=PROCESS_LIFE)
            self._slave = Slave(TestRunner)
        return self._slave

    def _set_browser_name(self, browser):
        # Set the default browser to use from now on
        self._browser_name = browser or self._browser_name

    def _get_browser_name(self):
        # Get the name of the current browser in use
        return self._browser_name or self.global_settings.get(
            'webdriver_browser')

    def reset(self):
        '''
        Reset as if we were from a fresh start.
        '''
        self.end_main()
        self._wdriver_mngr.quit_all_failed_webdrivers()
        self.kill_child()
        self.create_child()

    def new_browser(self, browser=None):
        '''
        Select a new current browser to run tests with. (will create if missing else reuse)
        :param browser: browser's name string. Eg:'Firefox', 'Chrome', 'PhantomJS'
        '''
        self._set_browser_name(browser)
        self.kill_child()
        self.create_child()

    def send_test(self, **test_config):
        '''
        Send tests config parameters to the Master process.
        (which in turn will send to TestRunner)
        '''
        if self._healthy_webdriver():
            self.send_recv('new_test', **test_config)
            self.test_config = test_config

    def test(self):
        '''
        Send parcial reload testing command.
        Means testing without recreating TestRunner subprocess
        '''
        if self._healthy_webdriver():
            cmd = 'partial_callback'
            ans = self.send_recv(cmd)
            self.log.e(ans.error)
            return ans

    def _healthy_webdriver(self):
        # Check if used webdrivers are in healthy status
        if self._wdriver_mngr.quit_all_failed_webdrivers():
            self.log.w('Webdriver failed. Restarting subprocesses...')
            # Restart browser if needed
            self.new_browser()
            return False
        return True

    def send(self, cmd, *args, **kwargs):
        '''
        Send arbitrary commands to the Master subprocess.
        Also make sure no remaining incoming data is in the pipe buffer
        before sending.
        
        :param cmd: method name of Master class
        :param args: variable args matching the signature of the remote method
        :param kwargs: variable keyword args matching the signature of the remote method
        '''
        while self.poll():
            self.log.i('Remaining in buffer: %r' % self.recv())
        return super(Main, self).send(cmd, *args, **kwargs)

    def kill_child(self):
        '''
        Send a kill command to the Master subprocess.
        If unable to gently die, we force killing Master subprocess.
        '''
        answer = self.kill(block=True, timeout=3)
        self._force_kill(self._child_pids)
        self._slave = None
        self._child_pids = []
        return answer

    def _force_kill(self, child_pids):
        '''
        Fallback mechanism that sends SIGKILL signal if any subprocess is still up.
        :param child_pids: iterable of subprocesses pids
        '''
        def process_running(pid):
            # Check For the existence of a unix pid.
            try:
                # Why not use signal.SIG_DFL ? (= 0)
                # Seems 0 will kill a process on Windows
                # http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
                os.kill(pid, 0)
                return True
            except OSError:
                return False

        for name, pid in child_pids:
            if process_running(pid):
                self.log.w('Pid (%r,%r) still up. Sending SIGKILL...' %
                           (name, pid))
                os.kill(pid, signal.SIGKILL)

    def end_main(self):
        '''
        Function we call when leaving the main loop or when resetting 
        the testing.
        '''
        if self._level_mngr:
            self._level_mngr.exit_level()
            self._level_mngr = None

    def steal_xpathbrowser(self, browser):
        '''
        Get an XpathBrowser instance bypassing any locking mechanism. (debugging purposes)
        :param browser: browser's name string
        '''
        browser = self._wdriver_mngr.expand_browser_name(browser)
        webdrivers = self._wdriver_mngr.list_webdrivers(which='all')
        for wd, (brwsr, _) in webdrivers.iteritems():
            if browser == brwsr:
                return XpathBrowser(None, wd)
Exemplo n.º 25
0
class Main(ParentBase):
    '''
    This class contains the "main loop" logic of the autotest command
    It will create 2 forked subprocess as:
        Main Process (this one)
          Master Subprocess (Child)
            TestRunner Subprocess (Grand Child)

    Roles are as:
        Main: where the CLI loop is done, sending commands to Master.
        Master: where file watching happens; events from Main and TestRunner are integrated
            decides whether to: trigger tests, kill TestRunner and recreate it.
        TestRunner: where tests are loaded and ran, test results are sent back to Master.
    '''

    def __init__(self):
        '''
        Initialize attributes
        '''
        self._timeout = 1
        self._ishell = None   # Ipython Shell instance
        self.test_config = {} # Configuration parameters sent for each test round
        self._slave = None    # Slave instance (configures how tests are ran)
        self._child_pids = [] # Store pids of children, in case we need to kill them
        self._wdriver_mngr = WebdriverManager() # common WebdriverManager instance
        self._browser_name = None # Current selected browser name
        self._level_mngr = None # WebdriverLevelManager for each time we enter/leave a "webdriver life level" 

    def run(self, test_config, embed_ipython=False, block=False):
        '''
        Runs the main CLI loop.
        If ipython is not present it will fallback to gdb as CLI.

        :param test_config: initial configuration parameters
        :param embed_ipython: if True, it will embed a interactive shell.
        :param block: block waiting for events (in case no shell was enabled)
        '''
        self.log.set_pre_post(pre='Autotest CLI')
        self.test_config = test_config
        self.create_child()
        if embed_ipython:
            from .ipython_extension import load_extension
            def extension(ipython):
                return load_extension(ipython, self)
            self._ishell = IpythonEmbedder().embed(extension)
            self.kill_child()
            self.end_main()
            self._wdriver_mngr.stop_display()
            raise SystemExit(0)
        elif block:
            self.log.i(self.recv())

    def create_child(self):
        '''
        Create Master role subprocess
        '''
        slave = self._build_slave()

        def callback(conn):
            if self._ishell:
                self._ishell.exit_now = True
            sys.stdin.close()
            master = Master(conn, slave)
            poll = master.io_loop(self.test_config)
            while True:
                poll.next()

        self.start_subprocess(callback, pre='Master')
        slave_pid = self.call_remote(Master.get_subprocess_pid)
        self._child_pids.append(('slave_pid', slave_pid))
        self._child_pids.append(('master_pid', self.get_subprocess_pid()))

    def _build_slave(self):
        # Build the Slave class instance (used to control how tests are ran)
        if not self._slave:
            # Release no longer used webdriver
            if self._level_mngr:
                self._level_mngr.release_driver()
            # Quit those drivers not responding
            self._wdriver_mngr.quit_all_failed_webdrivers()
            self._wdriver_mngr.set_browser(self._get_browser_name())
            # Enter the level again
            self._level_mngr = self._wdriver_mngr.enter_level(level=PROCESS_LIFE)
            self._slave = Slave(TestRunner)
        return self._slave

    def _set_browser_name(self, browser):
        # Set the default browser to use from now on
        self._browser_name = browser or self._browser_name
        
    def _get_browser_name(self):
        # Get the name of the current browser in use
        return self._browser_name or self.global_settings.get('webdriver_browser')

    def reset(self):
        '''
        Reset as if we were from a fresh start.
        '''
        self.end_main()
        self._wdriver_mngr.quit_all_failed_webdrivers()
        self.kill_child()
        self.create_child()

    def new_browser(self, browser=None):
        '''
        Select a new current browser to run tests with. (will create if missing else reuse)
        :param browser: browser's name string. Eg:'Firefox', 'Chrome', 'PhantomJS'
        '''
        self._set_browser_name(browser)
        self.kill_child()
        self.create_child()

    def send_test(self, **test_config):
        '''
        Send tests config parameters to the Master process.
        (which in turn will send to TestRunner)
        '''
        if self._healthy_webdriver():
            self.send_recv('new_test', **test_config)
            self.test_config = test_config

    def test(self):
        '''
        Send parcial reload testing command.
        Means testing without recreating TestRunner subprocess
        '''
        if self._healthy_webdriver():
            cmd = 'partial_callback'
            ans = self.send_recv(cmd)
            self.log.e(ans.error)
            return ans

    def _healthy_webdriver(self):
        # Check if used webdrivers are in healthy status
        if self._wdriver_mngr.quit_all_failed_webdrivers():
            self.log.w('Webdriver failed. Restarting subprocesses...')
            # Restart browser if needed
            self.new_browser()
            return False
        return True

    def send(self, cmd, *args, **kwargs):
        '''
        Send arbitrary commands to the Master subprocess.
        Also make sure no remaining incoming data is in the pipe buffer
        before sending.
        
        :param cmd: method name of Master class
        :param args: variable args matching the signature of the remote method
        :param kwargs: variable keyword args matching the signature of the remote method
        '''
        while self.poll():
            self.log.i('Remaining in buffer: %r' % self.recv())
        return super(Main, self).send(cmd, *args, **kwargs)

    def kill_child(self):
        '''
        Send a kill command to the Master subprocess.
        If unable to gently die, we force killing Master subprocess.
        '''
        answer = self.kill(block=True, timeout=3)
        self._force_kill(self._child_pids)
        self._slave = None
        self._child_pids = []
        return answer

    def _force_kill(self, child_pids):
        '''
        Fallback mechanism that sends SIGKILL signal if any subprocess is still up.
        :param child_pids: iterable of subprocesses pids
        '''
        def process_running(pid):
            # Check For the existence of a unix pid.
            try:
                # Why not use signal.SIG_DFL ? (= 0)
                # Seems 0 will kill a process on Windows
                # http://stackoverflow.com/questions/568271/how-to-check-if-there-exists-a-process-with-a-given-pid
                os.kill(pid, 0)
                return True
            except OSError:
                return False
        for name, pid in child_pids:
            if process_running(pid):
                self.log.w('Pid (%r,%r) still up. Sending SIGKILL...' % (name, pid))
                os.kill(pid, signal.SIGKILL)

    def end_main(self):
        '''
        Function we call when leaving the main loop or when resetting 
        the testing.
        '''
        if self._level_mngr:
            self._level_mngr.exit_level()
            self._level_mngr = None

    def steal_xpathbrowser(self, browser):
        '''
        Get an XpathBrowser instance bypassing any locking mechanism. (debugging purposes)
        :param browser: browser's name string
        '''
        browser = self._wdriver_mngr.expand_browser_name(browser)
        webdrivers = self._wdriver_mngr.list_webdrivers(which='all')
        for wd, (brwsr, _) in webdrivers.iteritems():
            if browser == brwsr:
                return XpathBrowser(None, wd)
Exemplo n.º 26
0
 def __init__(self):
     super(TestRunner, self).__init__()
     self._level_mngr = WebdriverManager().enter_level(
         level=TEST_RUNNER_LIFE)
Exemplo n.º 27
0
class TestRunner(ChildBase, TestRunnerBase):
    '''
    Responsabilities
        - Import the Test Class
        - Run test over all methods or specific methods
        - Report any errors
    '''
    def __init__(self):
        super(TestRunner, self).__init__()
        self._level_mngr = WebdriverManager().enter_level(
            level=TEST_RUNNER_LIFE)

    def test(self, test_paths, argv=[], smoke=False):
        '''
        :param test_paths: iterable like ['package.module.test_class.test_method', ...]
        '''
        results = TestResults()
        if smoke or not test_paths:
            self.log.i('Ignoring %r \n  (smoke mode or no tests found)' %
                       list(test_paths))
            return results
        level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)
        for tpath in test_paths:
            class_ = self._import_test(tpath)
            if isinstance(class_, TestException):
                results.append_result(tpath, class_)
            else:
                result = self._run_test(tpath, argv, class_)
                results.append_result(tpath, result)
        level_mngr.exit_level()
        return results

    def io_loop(self, conn, stdin=None, stdout=None, stderr=None):
        while True:
            self._dispatch_cmds(conn)

    def _receive_kill(self, *args, **kwargs):
        self._tear_down_process()
        self._level_mngr.exit_level()

    def _run_test(self, test_path, argv, class_):
        try:
            _, _, methstr = self._split_path(test_path)
            suite = unittest.TestSuite()
            suite.addTest(class_(methstr))
            runner = unittest.TextTestRunner()
            self._setup_process(class_, test_path, argv)
            return runner.run(suite)
        except Exception as e:
            return self.reprex(e)

    def _split_path(self, test_path):
        return self.split_test_path(test_path, meth=True)

    def _import_test(self, test_path):
        modstr, clsstr, _ = self._split_path(test_path)
        try:
            module = importlib.import_module(modstr)
            module = reload(module)
            class_ = getattr(module, clsstr)
            return class_
        except Exception as e:
            return self.reprex(e)
Exemplo n.º 28
0
 def setUp(self):
     # We need to enter "single test level" of life for each test
     # It will initialize the webdriver if no webdriver is present from upper levels
     self._level_mngr = WebdriverManager().enter_level(level=SINGLE_TEST_LIFE)
     # Get Xpath browser
     self.browser = self._level_mngr.get_xpathbrowser(name=__name__)
Exemplo n.º 29
0
class TestRunner(ChildBase, TestRunnerBase):

    '''
    Responsabilities
        - Import the Test Class
        - Run test over all methods or specific methods
        - Report any errors
    '''

    def __init__(self):
        super(TestRunner, self).__init__()
        self._level_mngr = WebdriverManager().enter_level(level=TEST_RUNNER_LIFE)

    def test(self, test_paths, argv=[], smoke=False):
        '''
        :param test_paths: iterable like ['package.module.test_class.test_method', ...]
        '''
        results = TestResults()
        if smoke or not test_paths:
            self.log.i('Ignoring %r \n  (smoke mode or no tests found)' %
                       list(test_paths))
            return results
        level_mngr = WebdriverManager().enter_level(level=TEST_ROUND_LIFE)
        for tpath in test_paths:
            class_ = self._import_test(tpath)
            if isinstance(class_, TestException):
                results.append_result(tpath, class_)
            else:
                result = self._run_test(tpath, argv, class_)
                results.append_result(tpath, result)
        level_mngr.exit_level()
        return results

    def io_loop(self, conn, stdin=None, stdout=None, stderr=None):
        while True:
            self._dispatch_cmds(conn)

    def _receive_kill(self, *args, **kwargs):
        self._tear_down_process()
        self._level_mngr.exit_level()

    def _run_test(self, test_path, argv, class_):
        try:
            _, _, methstr = self._split_path(test_path)
            suite = unittest.TestSuite()
            suite.addTest(class_(methstr))
            runner = unittest.TextTestRunner()
            self._setup_process(class_, test_path, argv)
            return runner.run(suite)
        except Exception as e:
            return self.reprex(e)

    def _split_path(self, test_path):
        return self.split_test_path(test_path, meth=True)

    def _import_test(self, test_path):
        modstr, clsstr, _ = self._split_path(test_path)
        try:
            module = importlib.import_module(modstr)
            module = reload(module)
            class_ = getattr(module, clsstr)
            return class_
        except Exception as e:
            return self.reprex(e)
Exemplo n.º 30
0
 def setUp(self):
     self.__level_mngr = WebdriverManager().enter_level(
         level=SINGLE_TEST_LIFE)
     webdriver = self.__level_mngr.acquire_driver()
     logger = Logger(__name__)
     self.browser = XpathBrowser('', webdriver, logger, settings={})
Exemplo n.º 31
0
 def __init__(self):
     super(TestRunner, self).__init__()
     self._level_mngr = WebdriverManager().enter_level(level=TEST_RUNNER_LIFE)