简体   繁体   中英

Python unittest running multiple times

tldr; My unittests are running twice. Any idea why?

Consider that I have 2 files:

a.py
checker.py

I have a weird requirement for a.py. a.py has the following code and is required to have this code:

import checker

def factorial(n):
    if n == -1:
        raise Exception("Raised this exception on purpose")
    result = 1
    for i in range(1,n+1):
        result *= i

    return result

total = 53

checker.runTests()

I'd need to be able to run the tests for factorial in checker.py

import unittest


class MyTestCase(unittest.TestCase):
    def test_factorial3(self):
        import a
        self.assertEqual(a.factorial(3), 6)

    def test_factorial4(self):
        import a
        self.assertEqual(a.factorial(4), 24)

    def test_factorial5(self):
        import a
        self.assertEqual(a.factorial(5), 120)

    def test_factorialnegative1(self):
        import a
        self.assertEqual(a.factorial(-1), 0)

    def test_total(self):
        import a
        self.assertEqual(a.total, 53)
def runTests():
    runner = unittest.TextTestRunner(verbosity=2)
    suite = unittest.TestLoader().loadTestsFromTestCase(MyTestCase)
    runner.run(suite)

I'm open to suggestions on how to improve checker.py if there's any better ways to handle the circular dependencies. However, my issue is that when I run a.py, I don't get expected output, particularly the tests are run twice? See:

test_factorial3 (cisc106checker.MyTestCase) ... test_factorial3 (cisc106checker.MyTestCase) ... ok test_factorial4 (cisc106checker.MyTestCase) ... ok test_factorial5 (cisc106checker.MyTestCase) ... ok test_factorialnegative1 (cisc106checker.MyTestCase) ... ERROR test_total (cisc106checker.MyTestCase) ... ok

====================================================================== ERROR: test_factorialnegative1 (cisc106checker.MyTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/tnj/PycharmProjects/AutoExam/cisc106checker.py", line 21, in test_factorialnegative1 self.assertEqual(x.factorial(-1), 0) File "/Users/tnj/PycharmProjects/AutoExam/mattsapQ16.py", line 10, in factorial raise Exception("Matt Raised this exception on purpose") Exception: Matt Raised this exception on purpose

---------------------------------------------------------------------- Ran 5 tests in 0.001s

FAILED (errors=1) ok test_factorial4 (cisc106checker.MyTestCase) ... ok test_factorial5 (cisc106checker.MyTestCase) ... ok test_factorialnegative1 (cisc106checker.MyTestCase) ... ERROR test_total (cisc106checker.MyTestCase) ... ok

====================================================================== ERROR: test_factorialnegative1 (cisc106checker.MyTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/tnj/PycharmProjects/AutoExam/cisc106checker.py", line 21, in test_factorialnegative1 self.assertEqual(x.factorial(-1), 0) File "/Users/tnj/PycharmProjects/AutoExam/mattsapQ16.py", line 10, in factorial raise Exception("Matt Raised this exception on purpose") Exception: Matt Raised this exception on purpose

---------------------------------------------------------------------- Ran 5 tests in 0.005s

FAILED (errors=1)

However, when I run it from checker.py, it's only run once. What is going on? Why is it running twice?

The snippet outside of you function in a.py

total = 53 
checker.runTests()

Is executed once when you run a.py and then again when you import it in checker.py . So runTests() is executed twice.

Maybe the better thing to do is to ask, "What is the best scaffolding I can give to my students so it's easy for them to write and run tests?" They will be editing both the product file (a.py) and the test file (checker.py), so why choose one over the other? Have them run checker.py to run the tests. Then you won't be introducing import loops, and they will have a simple structure they can understand.

Short version: Get rid of the import checker at the beginning and of the checker.runTests() at the end of the file with the solution.

Longer version:

By having a call to the tests inside your "production code" you are attaching your code to the tests. And you don't really want to do this.

To run your tests you could change the end of the tests file to

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

and run the tests by calling python my_test_file.py .

Following the step described in the short version will also solve the circular dependencies issue you mentioned.

Another easy-to-do improvement: You can write import a in the second line and get rid of all the duplicated import a lines.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM