Skip to content

Commit 4410ef7

Browse files
authored
Merge pull request #3 from lpm0073/mcdaniel_20230426c
Mcdaniel 20230426c - add automated unit tests
2 parents f561f07 + 99cea64 commit 4410ef7

File tree

5 files changed

+152
-124
lines changed

5 files changed

+152
-124
lines changed

.github/workflows/precommit.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

.github/workflows/security.yml

Lines changed: 0 additions & 24 deletions
This file was deleted.

.github/workflows/tests.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Run all tests
2+
3+
on:
4+
pull_request:
5+
push:
6+
7+
jobs:
8+
tests:
9+
name: tests
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/[email protected]
14+
- name: Set up Python 3.x
15+
uses: actions/setup-python@v4
16+
with:
17+
python-version: "3.10"
18+
- run: python -m pip install -r requirements/local.txt
19+
- run: python -m tests

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,33 @@ A Python decorator to generate redacted and nicely formatted log entries. Works
1414
```python
1515
from secure_logger.decorators import secure_logger
1616

17-
class TestClass(object):
17+
class Foo(object):
1818

1919
@secure_logger()
20-
def test_2(self, test_dict, test_list):
20+
def bar(self, dict_data, list_data):
2121
pass
2222

2323
# call your method, passing some sensitive data
24-
test_dict = {
24+
dict_data = {
2525
'not_a_sensitive_key': 'you-can-see-me',
2626
'aws-access-key_id': conf.AWS_ACCESS_KEY_ID,
2727
'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY
2828
}
29-
test_list = ['foo', 'bar']
30-
o = TestClass()
31-
o.test_2(test_dict=test_dict, test_list=test_list)
29+
list_data = ['foo', 'bar']
30+
foo = Foo()
31+
foo.bar(dict_data=dict_data, list_data=list_data)
3232
```
3333

3434
Log output:
3535

3636
```log
37-
INFO:secure_logger: __main__.TestClass().test_2() keyword args: {
38-
"test_dict": {
37+
INFO:secure_logger: __main__.Foo().bar() keyword args: {
38+
"dict_data": {
3939
"not_a_sensitive_key": "you-can-see-me",
40-
"aws-access-key-id": "*** -- REDACTED -- ***",
41-
"aws-secret-access-key": "*** -- REDACTED -- ***"
40+
"aws-access-key-id": "*** -- secure_logger() -- ***",
41+
"aws-secret-access-key": "*** -- secure_logger() -- ***"
4242
},
43-
"test_list": [
43+
"list_data": [
4444
"foo",
4545
"bar"
4646
]
@@ -52,21 +52,21 @@ INFO:secure_logger: __main__.TestClass().test_2() keyword args: {
5252
```python
5353
from secure_logger.masked_dict import masked_dict, masked_dict2str
5454

55-
test_dict = {
55+
dict_data = {
5656
'not_a_sensitive_key': 'you-can-see-me',
5757
'aws-access-key_id': conf.AWS_ACCESS_KEY_ID,
5858
'aws-secret-access-key': conf.AWS_SECRET_ACCESS_KEY
5959
}
60-
print(masked_dict2str(test_dict))
60+
print(masked_dict2str(dict_data))
6161
```
6262

6363
Output:
6464

6565
```bash
6666
{
6767
"not_a_sensitive_key": "you-can-see-me",
68-
"aws-access-key-id": "*** -- REDACTED -- ***",
69-
"aws-secret-access-key": "*** -- REDACTED -- ***"
68+
"aws-access-key-id": "*** -- secure_logger() -- ***",
69+
"aws-secret-access-key": "*** -- secure_logger() -- ***"
7070
}
7171
```
7272

tests.py

Lines changed: 118 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,156 @@
11
# -*- coding: utf-8 -*-
2+
# flake8: noqa
23
"""
34
Simple test bank.
45
56
Test the three use cases that we care about.
67
"""
8+
import unittest
79
import logging
10+
import json
811

912
from secure_logger.decorators import secure_logger
10-
from secure_logger.masked_dict import masked_dict, masked_dict2str
13+
from secure_logger.masked_dict import (
14+
masked_dict,
15+
masked_dict2str,
16+
DEFAULT_REDACTION_MESSAGE,
17+
)
1118

12-
logging.basicConfig(level=logging.DEBUG)
1319

14-
MY_SENSITIVE_KEYS = [
15-
"client_id",
16-
"client_secret",
17-
"aws_access_key_id",
18-
"aws_secret_access_key",
19-
]
20+
###############################################################################
21+
# TEST BANK
22+
###############################################################################
23+
class TestMaskedDict(unittest.TestCase):
24+
test_dict = {
25+
"insensitive_key": "you-can-see-me",
26+
"aws_access_key_id": "i-am-hidden",
27+
"aws_secret_access_key": "so-am-i",
28+
}
29+
expected_dict = {
30+
"insensitive_key": "you-can-see-me",
31+
"aws_access_key_id": DEFAULT_REDACTION_MESSAGE,
32+
"aws_secret_access_key": DEFAULT_REDACTION_MESSAGE,
33+
}
34+
35+
def test_masked_dict(self):
36+
md = masked_dict(self.test_dict)
37+
self.assertDictEqual(md, self.expected_dict)
38+
39+
def test_masked_dict2str(self):
40+
md2s = masked_dict2str(self.test_dict)
41+
md2s_to_json = json.loads(md2s)
42+
self.assertDictEqual(md2s_to_json, self.expected_dict)
43+
44+
45+
class TestMaskedDictCaseSensitivity(unittest.TestCase):
46+
test_dict = {
47+
"insensitive_key": "you-can-see-me",
48+
"AWs_AcCEss_KeY_iD": "i-am-very-hidden",
49+
"AWS_SECRET_ACCESS_KEY": "so-am-i",
50+
}
51+
expected_dict = {
52+
"insensitive_key": "you-can-see-me",
53+
"AWs_AcCEss_KeY_iD": DEFAULT_REDACTION_MESSAGE,
54+
"AWS_SECRET_ACCESS_KEY": DEFAULT_REDACTION_MESSAGE,
55+
}
56+
57+
def test_masked_dict(self):
58+
md = masked_dict(self.test_dict)
59+
self.assertDictEqual(md, self.expected_dict)
60+
61+
def test_masked_dict2str(self):
62+
md2s = masked_dict2str(self.test_dict)
63+
md2s_to_json = json.loads(md2s)
64+
self.assertDictEqual(md2s_to_json, self.expected_dict)
65+
2066

67+
class TestCustomParams(unittest.TestCase):
68+
visible_value = "i should be visible"
69+
custom_keys = ["foo", "bar"]
70+
custom_message = "--REDACTED--"
71+
test_dict = {"foo": "i should be hidden", "bar": "me too", "visible_key": visible_value}
2172

22-
@secure_logger()
23-
def test_1(msg):
24-
"""Test 1: a simple module function."""
25-
print("test 1: " + msg) # noqa: T201
73+
def test_custom_keys(self):
74+
expected_result = {
75+
"foo": DEFAULT_REDACTION_MESSAGE,
76+
"bar": DEFAULT_REDACTION_MESSAGE,
77+
"visible_key": self.visible_value,
78+
}
79+
masked_test_dict = masked_dict(self.test_dict, self.custom_keys)
80+
self.assertDictEqual(masked_test_dict, expected_result)
2681

82+
def test_custom_keys_and_message(self):
83+
expected_result = {"foo": self.custom_message, "bar": self.custom_message, "visible_key": self.visible_value}
84+
masked_test_dict = masked_dict(self.test_dict, self.custom_keys, self.custom_message)
85+
self.assertDictEqual(masked_test_dict, expected_result)
2786

28-
class TestClass(object):
29-
"""Test class method logging."""
3087

88+
class TestModuleDefDecorator(unittest.TestCase):
3189
@secure_logger()
32-
def test_2(self, test_dict, test_list):
33-
"""Test class input parameter as objects."""
90+
def mock_decorated_def(self, msg):
91+
"""Test 1: a simple module function."""
3492
pass
3593

36-
@secure_logger(sensitive_keys=["aws_secret_access_key"], indent=10, message="-- Forbidden! --")
37-
def test_4(self, test_dict, test_list):
38-
"""Test class input parameter as objects."""
39-
pass
94+
def test_decorator_output(self):
95+
hello_world = json.dumps(["'hello world'"])
96+
hello_world = "'hello world'"
4097

98+
expected_output = (
99+
"INFO:secure_logger.decorators:secure_logger: __main__.mock_decorated_def() ['<__main__.TestModuleDefDecorator testMethod=test_decorator_output>', "
100+
+ hello_world
101+
)
102+
with self.assertLogs(level=logging.DEBUG) as cm:
103+
self.mock_decorated_def("hello world")
41104

42-
@secure_logger()
43-
class Test3:
44-
"""Test 3: decorate a class."""
105+
self.assertEqual(cm.output[0][0:100], expected_output[0:100])
45106

46-
pass
47107

108+
class TestClassMethodDecorator(unittest.TestCase):
109+
class MockClass(object):
110+
"""Test class method logging."""
48111

49-
if __name__ == "__main__":
50-
# test 1
51-
print("test 1 - default parameters on module function") # noqa: T201
52-
test_1("hello world")
112+
@secure_logger()
113+
def decorator_with_defaults(self, test_dict, test_list):
114+
"""Test class input parameter as objects."""
115+
pass
116+
117+
@secure_logger(sensitive_keys=["aws_secret_access_key"], indent=10, message="-- Forbidden! --")
118+
def decorator_with_custom_params(self, test_dict, test_list):
119+
"""Test class input parameter as objects."""
120+
pass
53121

54-
# test 2
55-
print("test 2 - default parameters on class method") # noqa: T201
56122
test_dict = {
57123
"insensitive_key": "you-can-see-me",
58124
"aws_access_key_id": "i-am-hidden",
59125
"aws_secret_access_key": "so-am-i",
60126
}
61127
test_list = ["foo", "bar"]
62-
o = TestClass()
63-
o.test_2(test_dict=test_dict, test_list=test_list)
128+
mock_class = MockClass()
64129

65-
# test 3
66-
print("test 3 - default parameters on class definition") # noqa: T201
67-
test3 = Test3()
130+
def test_class_method_with_default_params(self):
131+
expected_output = "INFO:secure_logger.decorators:secure_logger: __main__.decorator_with_defaults() ['<__main__.TestClassMethodDecorator.MockClass"
68132

69-
# test 4
70-
print("test 4 - custom parameters") # noqa: T201
71-
o.test_4(test_dict=test_dict, test_list=test_list)
133+
with self.assertLogs(level=logging.DEBUG) as cm:
134+
self.mock_class.decorator_with_defaults(self.test_dict, self.test_list)
72135

73-
# test 5
74-
print("test 5 - masked_dict() w defaults") # noqa: T201
75-
print(masked_dict(test_dict)) # noqa: T201
136+
self.assertEqual(cm.output[0][0:100], expected_output[0:100])
76137

77-
# test 6
78-
print("test 6 - masked_dict() with custom parameters") # noqa: T201
79-
print(masked_dict(test_dict, sensitive_keys=["insensitive_key"], message=" -- TEST 6 MESSAGE -- ")) # noqa: T201
80138

81-
# test 7
82-
print("test 7 - masked_dict2str() w defaults") # noqa: T201
83-
print(masked_dict2str(test_dict)) # noqa: T201
139+
class TestClassDecorator(unittest.TestCase):
140+
def test_class_with_default_params(self):
141+
@secure_logger()
142+
class MockDecoratedClass(object):
143+
"""Test 3: decorate a class."""
84144

85-
# test 8
86-
print("test 8 - masked_dict2str() w custom parameters") # noqa: T201
87-
md = masked_dict2str(test_dict, sensitive_keys=["insensitive_key"], message=" -- TEST 8 MESSAGE -- ", indent=2)
88-
print(md) # noqa: T201
145+
pass
89146

90-
# test 9
91-
print("test 9 - masked_dict2str() upper case keys") # noqa: T201
92-
test_dict = {
93-
"insensitive_key": "you-can-see-me",
94-
"AWS_ACCESS_KEY_ID": "i-am-hidden",
95-
"AWS_Secret_Access_Key": "so-am-i",
96-
}
97-
print(test_dict) # noqa: T201
98-
print(masked_dict(test_dict)) # noqa: T201
99-
print(masked_dict2str(test_dict)) # noqa: T201
147+
expected_output = "INFO:secure_logger.decorators:secure_logger: __main__.MockDecoratedClass. "
148+
149+
with self.assertLogs(level=logging.DEBUG) as cm:
150+
mock_decoratorated_class = MockDecoratedClass()
151+
152+
self.assertEqual(cm.output[0][0:100], expected_output[0:100])
153+
154+
155+
if __name__ == "__main__":
156+
unittest.main()

0 commit comments

Comments
 (0)