0

I have some python code and I want to coverage it with unittest. My simple code is:

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()

Help me to create some unittest for this lines of code. I create some class GitRepoParserTest in my python tests:

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

But I don't understand how I need to write tests for create_new_service function.

Please help me.

Thank you.

3
  • understanding the input of the function (pre-condition) and expected output/side effect (post condition) may guide you in the right direction Commented Oct 14, 2019 at 22:06
  • Call create_new_service, afterwards open the target property file and verify it has the correct contents. Commented Oct 15, 2019 at 8:58
  • Does this really relate to pytest? I'm asking because this affects the approach you would need to take (mocking, temporary directories, etc.). Commented Oct 15, 2019 at 10:19

1 Answer 1

2

Here is the unit test solution for 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()

Unit test result with coverage report:

...
----------------------------------------------------------------------
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%

As you can see, there is still a if condition branch left. You can finish it by yourself.

Source code: https://github.com/mrdulin/python-codelab/tree/master/src/stackoverflow/58384586

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.