Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python unittest stops working when all test run together but individual tests work just fine

I'm learning how to use a unittest module and I came across something really annoying. I wrote this simple class.

class Employee:

    salary = 0
    savings = 0
    no_of_emp = 0
    eid = -1
    raise_amount = 0
    tags = set()

    def __init__(self, first, last, salary=None):
        self.first = first
        self.last = last
        self.salary = salary or self.salary
        Employee.no_of_emp += 1
        self.eid = Employee.gen_eid()

    @staticmethod
    def gen_eid():
        from random import random
        return round(random() * 10000000000000)

    def get_email(self):
        return f"{self.first}.{self.last}@gmail.com"

    def set_salary(self, pay):
        self.salary = pay

    def give_raise(self):
        new_salary = self.raise_amount * self.salary
        self.salary = new_salary
        return new_salary

    def add_savings(self, amount):
        self.savings += amount

    def add_tag(self, t):
        self.tags.add(t)

    def remove_tag(self, t):
        self.tags.remove(t)

    @classmethod
    def set_raise_amount(cls, amount):
        cls.raise_amount = amount

    @classmethod
    def from_string(cls, emp_str):
        try:
            first, last, salary = tuple(emp_str.split('-'))
            return cls(first, last, salary)
        except ValueError:
            print(f"Incorrect amount of arguments!!: {emp_str}")
            import sys
            sys.exit(1)

...and also this unit test which is supposed to test it

import unittest
from Employee import Employee


class TestEmployee(unittest.TestCase):

    def tearDown(self):
        self.no_of_emp = 0
        print("Setting number of emp to 0")

    def test_it_returns_email_address(self):
        # assume
        first_name = 'john'
        last_name = 'smith'
        emp = Employee(first_name, last_name)

        # action
        result = emp.get_email()

        # assert
        self.assertEqual(result, "[email protected]")

    def test_returns_eid(self):
        # assume
        first_name = 'john'
        last_name = 'smith'
        emp = Employee(first_name, last_name)

        # action
        result = emp.eid
        length = len(str(result))

        # assert
        self.assertNotEqual(result, -1)
        self.assertGreater(length, 8)
        self.assertIsInstance(result, int)

    def test_default_values(self):
        # assume
        first_name = 'john'
        last_name = 'smith'
        emp = Employee(first_name, last_name)
        emp2 = Employee(first_name, last_name)

        # action
        _salary = emp.salary
        _savings = emp.savings
        _tags = len(emp.tags)

        # assert
        self.assertEqual(_salary, 0)
        self.assertEqual(_savings, 0)
        self.assertEqual(emp.no_of_emp, 2)
        self.assertEqual(emp2.raise_amount, 0)
        self.assertEqual(_tags, 0)

    def test_adding_tags_works(self):
        # assume
        first_name = 'john'
        last_name = 'smith'
        emp = Employee(first_name, last_name)

        # action
        emp.add_tag('boss')
        _tags = len(emp.tags)

        # assert
        self.assertEqual(_tags, 1)
        self.assertEqual(emp.tags, {'boss'})


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

And the problem I'm having is that when I run my tests one by one they work as intended but when I run them all together it throws an error as such:

Ran 4 tests in 0.005s
FAILED (failures=1)
2 != 3

Expected :3
Actual   :2
File "/home/mike/PycharmProjects/class_example/tests/test_employee.py", line 53, in test_default_values
    self.assertEqual(emp.no_of_emp, 2)

It seems to me it somehow doesn't delete object instances after each class method is run, thus the no_of_emp keeps growing... but I was under the impression it will start each test with a clean plate class

like image 586
michal-ko Avatar asked Nov 23 '25 18:11

michal-ko


1 Answers

Did you mean to reset the global in setup?

    def setUp(self):
        Employee.no_of_emp = 0
        print("Setting number of emp to 0")
like image 122
quamrana Avatar answered Nov 26 '25 06:11

quamrana