user13469312
user13469312

Reputation: 31

How can I run unittest tests in random order

It seems tests are run in alphabetic order by default. I'm trying to run them in random order. The following shows what I have and the commented out lines at the bottom show the different commands I've tried. Nothing has worked so far. They all pass but run alphabetically each time.

import unittest
import random
from appium import webdriver
from PIL import Image, ImageChops

class SimpleNucleoTests(unittest.TestCase):

    @classmethod
    def setUpClass(self):
        # set up appium
        desired_caps = {}
        desired_caps["app"] = 'C:\\Temp\\Acist\\acist-nucleo\\AcistNucleoProtoGUI.exe'
        desired_caps['platformName'] = 'Windows'
        desired_caps['deviceName'] = 'WindowsPC'
        self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    @classmethod
    def tearDownClass(self):
        self.driver.quit()

    def test_defaultLayout(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.driver.get_screenshot_as_file('C:\\Temp\\ss_new.png')
        new_image = Image.open("C:\\temp\\ss_new.png")
        orig_image = Image.open("C:\\temp\\ss_orig.png")
        diff = ImageChops.difference(new_image, orig_image)
        if diff.getbbox():
            diff.show()
        else:
             print("Images are the same")
        self.assertEqual(diff.getbbox(), None)

    def getFlowRate(self):
        displaytext = self.driver.find_element_by_accessibility_id("FlowRateField").find_element_by_accessibility_id("InputTextBox").text
        return displaytext

    def test_defaultFlowRate(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.assertEqual(self.getFlowRate(), "4.0")

    def test_flowRateUp(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.driver.find_element_by_accessibility_id("UpButton").click()
        self.assertEqual(self.getFlowRate(), "4.5")

    def test_flowRateDown(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.driver.find_element_by_accessibility_id("DownButton").click()
        self.assertEqual(self.getFlowRate(), "3.5")

    def getVolume(self):
        displaytext = self.driver.find_element_by_accessibility_id("VolumeField").find_element_by_accessibility_id("InputTextBox").text
        return displaytext

    def test_defaultVolume(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.assertEqual(self.getVolume(), "6.0")

    def test_volumeUp(self):
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.driver.find_element_by_accessibility_id("VolumeField").find_element_by_accessibility_id("UpButton").click()
        self.assertEqual(self.getVolume(), "6.5")

    def test_volumeDown(self):
        print("Starting test 'volumeDown'")
        self.driver.find_element_by_accessibility_id("InjectorButton").click()
        self.driver.find_element_by_accessibility_id("VolumeField").find_element_by_accessibility_id("DownButton").click()
        self.assertEqual(self.getVolume(), "5.5")


if __name__ == '__main__':
    # unittest.TestLoader().main

    suite = unittest.TestLoader().sortTestMethodsUsing = None
    unittest.TextTestRunner(verbosity=2).run(suite)

    # unittest.TestLoader().sortTestMethodsUsing = None

    # unittest.TestLoader.sortTestMethodsUsing = lambda self, a, b: random.choice([1, 0, -1])

    # unittest.TestLoader.sortTestMethodsUsing = lambda _, x, y: cmp(y, x)

    # unittest.TextTestRunner(verbosity=2).main()

    # unittest.main(verbosity=2)

Upvotes: 3

Views: 328

Answers (1)

Pavel Shishpor
Pavel Shishpor

Reputation: 997

Here is a way to run tests in random order:

import random
import unittest

class Tests(unittest.TestCase):

    def test_1(self):
        pass
    def test_2(self):
        pass
    def test_3(self):
        pass
    def test_4(self):
        pass

class TestLoaderRandomTestOrder(unittest.TestLoader):
    def getTestCaseNames(self, *args, **kwargs):
        tests = super().getTestCaseNames(*args, **kwargs)
        random.shuffle(tests)
        return tests

if __name__ == '__main__':
    randomized_loader = TestLoaderRandomTestOrder()
    unittest.main(verbosity=2, testLoader=randomized_loader)

The unittest's documentation doesn't say that it is OK to redefine the getTestCaseNames method though. I don't think it is a big issue in practice. The following code also runs tests in random order. It uses only documented functionality but looks to be less generic:

import random
import unittest

class Tests(unittest.TestCase):

    def test_1(self):
        pass
    def test_2(self):
        pass
    def test_3(self):
        pass
    def test_4(self):
        pass

if __name__ == '__main__':
    tests = [t for t in dir(Tests) if t.startswith('test')]
    test_cases_in_random_order = ['Tests.' + t for t in tests]
    random.shuffle(test_cases_in_random_order)
    unittest.main(verbosity=2, defaultTest=test_cases_in_random_order)

Upvotes: 0

Related Questions