Flags
--unit | Python unit tests |
--functional | Python functional tests |
--coverage | Python coverage |
--specify=PATH | Python tests, use folder.file:class.function to specify test to run |
--pylint | Python source analysis |
--jsunit | Javascript unit tests |
--jscoverage | Javascript coverage |
--jsspecify=PATH | Javascript tests, use TestCase.testname to specify test to run |
--jslint | Javascript source analysis |
--grid | Running functional tests on the environment specified in tests.conf |
Python Unit tests
#Note that the 2 following functions will be called for module, very handy if we need to run a single test #So we do not need to specify a setup and teardown for each class def setup_module(): DBMgr.getInstance().startRequest() def teardown_module(): DBMgr.getInstance().abort() DBMgr.getInstance().endRequest() class TestCategories(unittest.TestCase): def testBasicAddAndRemoveConferences(self): [...] c1._addConference(conf1) assert (croot.getNumConferences()==0) [...]
Nosetests uses this regular expression (?:^|[b_.-])[Tt]est to fetch tests, so our naming conventions will be:
- Every file name has to end with _test.py (ie indicop_test.py)
- Every class has to start with Test with a capital T class TestIndicop(unittest.TestCase)
- Every function has to start with test def testIndicop()
Python Functional tests
from seleniumTestCase import SeleniumTestCase class ExampleTest(SeleniumTestCase): def setUp(self): SeleniumTestCase.setUp(self) [...] def tearDown(self): SeleniumTestCase.tearDown(self) if __name__ == "__main__": unittest.main()
Delete automatically conference at the end of execution (aka in teardown):
SeleniumTestCase.setConfID(self, sel.get_location())
- Selenium does not recognize Javascript auto-complete when a text is entered.
Solution: Enter the whole word by hand. - Javascript Calendar does not work either.
Solution: Enter the date by hand. - Do not make clicks or assertions on element containing IDs.
Solution: Use XPath instead. Xpaths are easy to find with Firefox's plugin XPather. - When replaying, Selenium can get confused with buttons' names and can end up clicking on the wrong button.
Solution: Once again, use XPath instead. Xpaths are easy to find with Firefox's plugin XPather. For example, instead of having td/tr/bla, we use the whole path which starts with html/etc - Popups and AJAX requests are very bothersome to test with Selenium. The latter would not wait for a page or a tab to load if we do not explicitly tell to do so.
Solution: Use Selenium waitForText function whenever a window pops up, a tab is loading or an AJAX request is sent.
waitForElementPresent will wait until the element introduced in Target is present. Note that you should always put an element that doesn't appear in the referer.
waitForText has a similar behaviour, but waits up until the element in Target has the value in Value.
And since Selenium is so unreliable about AJAX, to ensure that the action is performed, we do some brute forcing.
sel.click("addLink") for i in range(60): try: if "Session" == sel.get_text("link=Session"): break except: pass time.sleep(1) else: self.fail("time out")
Becomes:
sel.click("addLink") for i in range(60): try: if "Session" == sel.get_text("link=Session"): break else: sel.click("addLink") except: pass time.sleep(1) else: self.fail("time out")
The only line to add is else: sel.click("addLink").
Naming conventions same as Python unit tests.
Javascript Unit tests
MoveTest = TestCase("MoveTest"); MoveTest.prototype.setUp = function() { //your set up stuff }; MoveTest.prototype.testUpdateEntry = function() { //your tests assertEquals("MSG", expectedValue, actualValue); };