如何用unittest覆盖我的Python代码

时间:2019-10-14 22:02:43

标签: python pytest python-unittest

我有一些python代码,我想用unittest进行介绍。 我的简单代码是:

import os
import glob


class GitRepoParser:

    def __init__(self, repo_dir: str):
        self.repo_dir = repo_dir

    def get_folder_path(self, service_name: str) -> str:
        dir_path = '{path}/configuration/settings/{name}'.format(
            path=self.repo_dir,
            name=service_name
        )

        return dir_path

    def create_new_service(self, service_name: str, service_version: str):
        dir_path = self.get_folder_path(service_name)

        if os.path.isdir(dir_path):
            return

        os.makedirs(dir_path)
        property_file = '{folder}/{name}-deployment.properties'.format(
            folder=dir_path,
            name=service_name
        )

        current_path = os.path.dirname(__file__)
        template_path = os.path.join(
            current_path, '..', 'file_templates/deployment.properties'
        )

        if not os.path.isfile(template_path):
            return

        template_file = open(template_path, 'r')
        with open(property_file, 'w') as properties:
            for line in template_file:
                # Create parser for this code part
                value = line.strip().replace(
                    '%service_name%', service_name
                )

                properties.write(value + '\n')

        template_file.close()

帮我为这行代码创建一些单元测试。我在python测试中创建了一些GitRepoParserTest类:

class GitRepoParserTest(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()
        self.parser = GitRepoParser('/path-to-download')

    def test_get_folder_path(self):
        folder_path = self.parser.get_folder_path(service_name='oleg-service')
        self.assertIsInstance(folder_path, str)

    def test_create_new_service(self):
        pass

但是我不明白我需要如何为create_new_service函数编写测试。

请帮助我。

谢谢。

1 个答案:

答案 0 :(得分:2)

这是Python 3.7.5的单元测试解决方案:

test_GitRepoParser.py

import unittest
from unittest.mock import Mock, patch, mock_open, call
from GitRepoParser import GitRepoParser, os


class GitRepoParserTest(unittest.TestCase):
    def setUp(self):
        self.parser = GitRepoParser('/path-to-download')
        self.mock_open = mock_open(read_data='some data')

    def test_get_folder_path(self):
        folder_path = self.parser.get_folder_path(service_name='oleg-service')
        self.assertIsInstance(folder_path, str)

    @patch('GitRepoParser.os')
    def test_create_new_service_read_and_write_file_correctly(self, mock_os):
        mock_path = Mock()
        mock_path.dirname.return_value = '/Users/foo'
        mock_path.isdir.return_value = False
        mock_path.join.return_value = '/Users/whatever'
        mock_path.isfile.return_value = True
        mock_os.path = mock_path
        mock_os.makedirs = Mock()

        with patch('GitRepoParser.open', self.mock_open):
            self.parser.create_new_service(service_name='oleg-service', service_version='1.0')
            mock_path.isdir.assert_called_with('/path-to-download/configuration/settings/oleg-service')
            mock_os.makedirs.assert_called_with('/path-to-download/configuration/settings/oleg-service')
            expected = [call('/Users/whatever', 'r'),
                        call('/path-to-download/configuration/settings/oleg-service/oleg-service-deployment.properties', 'w')]
            self.mock_open.assert_has_calls(expected)
            handle = self.mock_open()
            handle.write.assert_called()
            handle.close.assert_called_once()

    @patch('GitRepoParser.os')
    def test_create_new_service_do_nothing_if_dir_path_is_dir(self, mock_os):
        mock_path = Mock()
        mock_path.isdir.return_value = True
        mock_os.path = mock_path
        mock_os.makedirs = Mock()

        self.parser.create_new_service(service_name='oleg-service', service_version='1.0')
        mock_path.isdir.assert_called_with('/path-to-download/configuration/settings/oleg-service')
        mock_os.makedirs.assert_not_called()


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

带有覆盖率报告的单元测试结果:

...
----------------------------------------------------------------------
Ran 3 tests in 0.023s

OK
Name                                               Stmts   Miss  Cover   Missing
--------------------------------------------------------------------------------
src/stackoverflow/58384586/GitRepoParser.py           24      1    96%   35
src/stackoverflow/58384586/test_GitRepoParser.py      37      0   100%
--------------------------------------------------------------------------------
TOTAL                                                 61      1    98%

如您所见,仍然有一个if条件分支。您可以自己完成。

源代码:https://github.com/mrdulin/python-codelab/tree/master/src/stackoverflow/58384586