I have a test suite as below:
import unittest
from selenium import webdriver
SAUCE_USERNAME = 'xxx'
SAUCE_ACCESS_KEY = 'xxx'
sauce = SauceClient(SAUCE_USERNAME, SAUCE_ACCESS_KEY)
browsers = [{"platform": "Mac OS X 10.9",
"browserName": "chrome",
"version": "31"},
{"platform": "Windows 8.1",
"browserName": "internet explorer",
"version": "11"}]
def on_platforms(platforms):
def decorator(base_class):
module = sys.modules[base_class.__module__].__dict__
for i, platform in enumerate(platforms):
d = dict(base_class.__dict__)
d['desired_capabilities'] = platform
name = "%s_%s" % (base_class.__name__, i + 1)
module[name] = new.classobj(name, (base_class,), d)
return decorator
@on_platforms(browsers)
class MyTestSuite(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.desired_capabilities['name'] = cls.id()
sauce_url = "http://%s:%s@ondemand.saucelabs.com:80/wd/hub"
cls.driver = webdriver.Remote(
desired_capabilities=cls.desired_capabilities,
command_executor=sauce_url % (SAUCE_USERNAME,SAUCE_ACCESS_KEY))
cls.driver.implicitly_wait(30)
def test_1from_sauce(self):
pass
def test_2from_sauce(self):
pass
@classmethod
def tearDownClass(cls):
cls.driver.quit()
if __name__ == "__main__":
unittest.main()
My goal is to run test_1from_sauce and test_2from_sauce for browsers/platforms in browsers and ALSO I do want to do both of them in a row on the browser that is setup on setUpClass. To explain more, I want to open a browser and do both tests then quit that driver and start another driver.
Right now when I run this code, I get this error: TypeError: unbound method setUpClass() must be called with SeleniumSauce_2 instance as first argument (got nothing instead)
I know there should be a modification in class and subclass declaration but I do not know what should I do or what part should I change.
EDITED: I omitted the following line and it worked fine:
cls.desired_capabilities['name'] = cls.id()
The code you show in your question is missing the imports for sys
and new
. Secondly, the error I get when I run your code after adding the right imports is not what you report in your question but this:
EE
======================================================================
ERROR: setUpClass (__main__.MyTestSuite_1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests.py", line 33, in setUpClass
cls.desired_capabilities['name'] = cls.id()
TypeError: unbound method id() must be called with MyTestSuite_1 instance as first argument (got nothing instead)
I've omitted a second ERROR
which is the same as above except that it is for MyTestSuite_2
rather than MyTestSuite_1
. The problem is pretty clear. You call the id()
member of cls
but id()
is an instance method not a class method so it needs an instance of the class, not the class itself. I'm not sure what it is you want in the end but if you use this for your setUpClass
, then the error no longer occurs and an attempt is made to connect:
@classmethod
def setUpClass(cls):
cls.desired_capabilities['name'] = cls.__name__
sauce_url = "http://%s:%s@ondemand.saucelabs.com:80/wd/hub"
cls.driver = webdriver.Remote(
desired_capabilities=cls.desired_capabilities,
command_executor=sauce_url % (SAUCE_USERNAME, SAUCE_ACCESS_KEY))
cls.driver.implicitly_wait(30)
The only modification is the first line of the method.
By the way, I don't get why you use new.classobj
. For one thing, the new
module is deprecated. Secondly, using the type
built-in rather than new.classobj
works.