Skip to content

Commit

Permalink
#15 Skeleton and parser for apply command
Browse files Browse the repository at this point in the history
+ mock_envs decorator can now be applied to test classes
+ mock_envs decorator was moved to a separate module
+ test for apply command parser and main function
+ test_main now uses mock_envs decorator also
  • Loading branch information
lancelote committed Jul 6, 2017
1 parent fd80eb1 commit 0729b68
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 20 deletions.
15 changes: 12 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
import argparse

from src.lib import get_api_envs
from src.utils import get_common_terms
from src.utils import get_common_terms, apply_regex


def create_parser():
parser = argparse.ArgumentParser(description='Quizlet Utils')
commands = parser.add_subparsers(title="Commands", dest="command")
commands.add_parser("common", help="Find duplicate terms across all sets")
commands = parser.add_subparsers(title='Commands', dest='command')
commands.required = True

commands.add_parser('common', help='Find duplicate terms across all sets')

apply = commands.add_parser('apply', help='Apply regex replace to set')
apply.add_argument('pattern', type=str, help='Pattern to search for')
apply.add_argument('repl', type=str, help='Replacement for pattern')
apply.add_argument('set_name', type=str, help='Word set to apply to')

return parser


Expand All @@ -20,6 +27,8 @@ def main():
api_envs = get_api_envs()
if args.command == 'common':
get_common_terms(*api_envs)
elif args.command == 'apply':
apply_regex(args.pattern, args.repl, args.set_name, *api_envs)


if __name__ == '__main__':
Expand Down
6 changes: 6 additions & 0 deletions src/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""User-available utilities."""
# ToDo: rename the module

from itertools import combinations

Expand All @@ -19,3 +20,8 @@ def get_common_terms(*api_envs):
common_terms.append(
(word_set_1, word_set_2, word_set_1.has_common(word_set_2)))
return common_terms


def apply_regex(pattern, repl, set_name, *api_envs):
"""Apply regex replace to all terms in word set."""
raise NotImplementedError # ToDo: complete the utility
17 changes: 1 addition & 16 deletions tests/src/test_lib.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
import os
import unittest
from functools import wraps
from unittest import mock

from src.lib import api_call, get_api_envs


def mock_envs(**envs):
"""Mock environment variables for test."""

def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
with mock.patch.dict(os.environ, envs, clear=True):
func(*args, **kwargs)

return wrapper

return decorator
from tests.utils import mock_envs


class TestGetApiEnvs(unittest.TestCase):
Expand Down
1 change: 1 addition & 0 deletions tests/src/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# ToDo: add tests
22 changes: 21 additions & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from unittest import mock

from main import create_parser, main
from tests.src.test_lib import mock_envs


class TestCreateParser(unittest.TestCase):
Expand All @@ -20,11 +21,30 @@ def test_common_command(self):
args = self.parser.parse_args(['common'])
self.assertEqual(args.command, 'common')

def test_apply_command_without_args(self):
with self.assertRaises(SystemExit):
self.parser.parse_args(['apply'])

def test_apply_command_with_all_args(self):
args = self.parser.parse_args(['apply', 'pattern', 'repl', 'set_name'])
self.assertEqual(args.command, 'apply')
self.assertEqual(args.pattern, 'pattern')
self.assertEqual(args.repl, 'repl')
self.assertEqual(args.set_name, 'set_name')


@mock_envs(CLIENT_ID='client_id', USER_ID='user_id')
class TestMain(unittest.TestCase):
@mock.patch('main.get_common_terms')
@mock.patch('main.get_api_envs', mock.Mock(return_value=[]))
@mock.patch('sys.argv', ['', 'common'])
def test_common(self, mock_get_common_terms):
main()
mock_get_common_terms.assert_called_once()

@mock.patch('main.apply_regex')
@mock.patch('sys.argv', ['', 'apply', 'pattern', 'repl', 'set_name'])
def test_apply(self, mock_apply_regex):
main()
mock_apply_regex.assert_called_once()

# ToDo: add decorator for mocking system arguments
30 changes: 30 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Utilities for tests."""

import inspect
from functools import wraps
from unittest import mock


def mock_envs(**envs):
"""Mock environment variables for test.
Can be applied to:
- any function
- test class - all test methods (starts with "test_*" will be decorated)
"""

def decorator(obj):
@wraps(obj)
def wrapper(*args, **kwargs):
with mock.patch.dict('os.environ', envs, clear=True):
obj(*args, **kwargs)

if inspect.isclass(obj):
for name, method in inspect.getmembers(obj, inspect.isfunction):
if name.startswith('test_'):
setattr(obj, name, decorator(method))
return obj
else:
return wrapper

return decorator

0 comments on commit 0729b68

Please sign in to comment.