Skip to content

Unify and simplify unit tests #64

@lamr02n

Description

@lamr02n

Description

Currently, the unit tests work but are often structured poorly or inconsistently. We should figure out a template for "perfect" unit tests and apply that to all the tests.

Possible test structure

For example, for a method like this:

def add(self, table_name: str, data: dict[str, Any]):
    """Adds the data to the batch for the table. Verifies the fields first."""
    self.tables.get(table_name).verify(data)
    self.batch.get(table_name).append(list(data.values()))

    if len(self.batch.get(table_name)) >= self.max_batch_size:
        self.insert(table_name)
    elif not self.timer:
        self._start_timer()

one possible test case could look as follows:

class TestAdd(unittest.TestCase):
    def setUp(self):
        with patch("src.monitoring.clickhouse_batch_sender.clickhouse_connect"):
            self.sut = ClickHouseBatchSender()

    def test_successful_with_starting_timer(self):
        # Arrange
        test_table_name = "test_table"
        test_data = {"value_1": 1, "value_2": 2}

        self.sut.tables = {test_table_name: Table(test_table_name, {})}
        self.sut.batch = {test_table_name: []}

        # Act
        with patch("src.monitoring.clickhouse_batch_sender.Table.verify"), \
             patch(
                 "src.monitoring.clickhouse_batch_sender.ClickHouseBatchSender._start_timer"
             ) as mock_start_timer:
            self.sut.add(test_table_name, test_data)

        # Assert
        self.sut.batch = {test_table_name: [1, 2]}
        mock_start_timer.assert_called_once()

The most notable changes to before are:

  • shorter, more descriptive test name, without the method's name included
  • clear Arrange, Act, Assert structure
  • patch for methods is done only where it is used, not in general with @patch
  • @patch should be used for global variables
  • everything that is not defined in that method is mocked, including other methods of the same class
  • everything that is not test case-specific, like the class setup, is isolated in the setUp method

Expected benefits

For maintainability reasons, it is useful to keep tests similar and easy to understand. The previous method has worked, but was harder to understand and update.

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions