mercredi 31 août 2016

Import Selenium IDE script as unittest.TestCase and Modify Dynamically

I am writing a program in python that will generate more robust data and reports from Selenium tests. I want to be able to export a test case from Selenium IDE from Firefox, and without modifying that specific exported python file, inject it into my script and allow my script to make modifications such as changing the webdriver (part of the implementation is for a Nagios server, which will use PhantomJS as the driver) and pulling request information and screenshots for reporting (Btw, I know I can change the driver in the IDE template, but it's just an example).

Lets say I have a file exported from the IDE path/to/mytests/search.py:

import...

class Search(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.base_url = 'http://www.example.com'

    def test_search(self):
        driver = self.driver
        driver.get(self.base_url)
        elem = self.driver.find_element_by_name('q')
        elem.send_keys('nagios')
        elem.send_keys(Keys.RETURN)
        assert 'No results found.' not in self.driver.page_source
        driver.get(self.base_url + '/status')
        assert 'OK' in self.driver.page_source

    def tearDown(self):
        self.driver.quit()

I want my script to be able to do this:

python -m my_wrapper mytests.search --url 'http://www.google.com'

Which will somehow import search.py, create a new testcase from it, and allow me to override the setUp/tearDown methods (changing the driver to PhantomJS, modifying the base URL from the sys.argv), and allow for catching errors and writing information related to where a failed test might have stopped (since there are two different URL calls, a screenshot of that page will be exported for wherever the driver is currently at).

I'm thinking something like my_wrapper.__main__:

# get 'mytests.search' from argparse
dirname, module = os.path.split('mytests.search'.replace('.', '/'))
suite = unittest.TestLoader().discover(dirname, pattern='%s.py' % module)

# Modify testcases here <-- THIS IS THE HARD PART
#
# Is there a way to inject the tests into another testCase class?
#
# class BaseClass(unittest.TestCase):
#    def setUp(self):
#        self.driver = webdriver.PhantomJS()
#        ...
#
#    def runTest(self): pass
#
#    def tearDown(self): ...
#
# then...
new_suite = unittest.TestSuite()
for sub_suite in master_suite:  #<-- iterating over the above suite here
    for tests in sub_suite._tests:  #<-- why do you have to do this twice?
        for test_name in tests._tests:
            # This doesn't work but show's my thought process
            mytest = BaseClass(methodName=test_name)
            setattr(mytest, test_func, getattr(tests, test_name))
            new_suite.addTest(mytest)

try:
    result = unittest.TextTestRunner(verbosity=2).run(new_suite)
except (SOME_SELENIUM_ERROR):
    # get the screenshot, save to file <-- don't know how to do this either

Anyway, any help into this would be appreciated. I would really like to keep this code as simple as possible using as much of what's available as I can.

Note: Other than selenium and PhantomJS, I'm also wary of using other dependencies like non-standard libraries, etc, for a number of policy reasons. ...

Aucun commentaire:

Enregistrer un commentaire