Skip to content

Commit e2e2866

Browse files
feat: add tests
1 parent e4d0d7c commit e2e2866

File tree

7 files changed

+303
-0
lines changed

7 files changed

+303
-0
lines changed

.github/workflows/test.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Test
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
matrix:
10+
python-version: ["3.9", "3.10"]
11+
steps:
12+
- uses: actions/checkout@v4
13+
- name: Set up Python ${{ matrix.python-version }}
14+
uses: actions/setup-python@v3
15+
with:
16+
python-version: ${{ matrix.python-version }}
17+
- name: Install dependencies
18+
run: |
19+
python -m pip install --upgrade pip
20+
pip install -r requirements.txt
21+
- name: Run unittests
22+
run: |
23+
python -m unittest discover

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

tests/test_api.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import unittest
2+
from unittest.mock import patch, Mock
3+
import sys
4+
import os
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
from manage_bitbucket_env import get_environment_uuid, get_variables
7+
8+
class TestAPI(unittest.TestCase):
9+
def setUp(self):
10+
self.logger = Mock()
11+
self.auth = Mock()
12+
self.workspace = 'ws'
13+
self.repo_slug = 'repo'
14+
self.deployment_name = 'env'
15+
self.env_uuid = 'uuid-123'
16+
17+
@patch('manage_bitbucket_env.requests.get')
18+
def test_get_environment_uuid_found(self, mock_get):
19+
mock_resp = Mock()
20+
mock_resp.json.return_value = {"values": [{"name": "env", "uuid": "uuid-123"}]}
21+
mock_resp.raise_for_status.return_value = None
22+
mock_get.return_value = mock_resp
23+
uuid = get_environment_uuid(self.workspace, self.repo_slug, self.deployment_name, self.auth, self.logger)
24+
self.assertEqual(uuid, 'uuid-123')
25+
mock_get.assert_called_once()
26+
27+
@patch('manage_bitbucket_env.requests.get')
28+
def test_get_environment_uuid_not_found(self, mock_get):
29+
mock_resp = Mock()
30+
mock_resp.json.return_value = {"values": [{"name": "other", "uuid": "uuid-999"}]}
31+
mock_resp.raise_for_status.return_value = None
32+
mock_get.return_value = mock_resp
33+
with self.assertRaises(ValueError):
34+
get_environment_uuid(self.workspace, self.repo_slug, self.deployment_name, self.auth, self.logger)
35+
36+
@patch('manage_bitbucket_env.requests.get')
37+
def test_get_variables(self, mock_get):
38+
mock_resp = Mock()
39+
mock_resp.json.return_value = {"values": [{"key": "A", "value": "1", "secured": False}]}
40+
mock_resp.raise_for_status.return_value = None
41+
mock_get.return_value = mock_resp
42+
vars = get_variables(self.workspace, self.repo_slug, self.env_uuid, self.auth, self.logger)
43+
self.assertEqual(vars[0]["key"], "A")
44+
45+
if __name__ == '__main__':
46+
unittest.main()

tests/test_arg_parser.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import unittest
2+
from unittest.mock import patch
3+
import sys
4+
import os
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
from manage_bitbucket_env import arg_parser
7+
8+
class TestArgParser(unittest.TestCase):
9+
def test_export_args(self):
10+
test_args = [
11+
'prog', '-w', 'ws', '-r', 'repo', '-d', 'env', '-o', 'out.json'
12+
]
13+
with patch.object(sys, 'argv', test_args):
14+
args = arg_parser()
15+
self.assertEqual(args.workspace, 'ws')
16+
self.assertEqual(args.repo_slug, 'repo')
17+
self.assertEqual(args.deployment_name, 'env')
18+
self.assertEqual(args.output, 'out.json')
19+
20+
def test_import_args(self):
21+
test_args = [
22+
'prog', '-w', 'ws', '-r', 'repo', '-d', 'env', '-i', 'in.json'
23+
]
24+
with patch.object(sys, 'argv', test_args):
25+
args = arg_parser()
26+
self.assertEqual(args.import_file, 'in.json')
27+
28+
def test_mutually_exclusive(self):
29+
test_args = [
30+
'prog', '-w', 'ws', '-r', 'repo', '-d', 'env'
31+
]
32+
with patch.object(sys, 'argv', test_args):
33+
with self.assertRaises(SystemExit):
34+
arg_parser()
35+
36+
if __name__ == '__main__':
37+
unittest.main()

tests/test_export_import.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import unittest
2+
from unittest.mock import patch, Mock
3+
import sys
4+
import os
5+
import tempfile
6+
import json
7+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
8+
from manage_bitbucket_env import export_variables, export_all_variables, export_secure_keys, import_variables
9+
10+
class TestExportImport(unittest.TestCase):
11+
def setUp(self):
12+
self.logger = Mock()
13+
self.auth = Mock()
14+
self.workspace = 'ws'
15+
self.repo_slug = 'repo'
16+
self.deployment_name = 'env'
17+
self.env_uuid = 'uuid-123'
18+
19+
@patch('manage_bitbucket_env.get_environment_uuid')
20+
@patch('manage_bitbucket_env.get_variables')
21+
def test_export_variables(self, mock_get_vars, mock_get_uuid):
22+
mock_get_uuid.return_value = self.env_uuid
23+
mock_get_vars.return_value = [
24+
{"key": "A", "value": "1", "secured": False},
25+
{"key": "B", "value": "2", "secured": True}
26+
]
27+
with tempfile.NamedTemporaryFile(delete=False) as tf:
28+
fname = tf.name
29+
try:
30+
export_variables(self.workspace, self.repo_slug, self.deployment_name, fname, self.auth, self.logger)
31+
with open(fname) as f:
32+
data = json.load(f)
33+
self.assertEqual(len(data), 1)
34+
self.assertEqual(data[0]["key"], "A")
35+
finally:
36+
os.unlink(fname)
37+
38+
@patch('manage_bitbucket_env.get_environment_uuid')
39+
@patch('manage_bitbucket_env.get_variables')
40+
def test_export_all_variables(self, mock_get_vars, mock_get_uuid):
41+
mock_get_uuid.return_value = self.env_uuid
42+
mock_get_vars.return_value = [
43+
{"key": "A", "value": "1", "secured": False},
44+
{"key": "B", "value": "2", "secured": True}
45+
]
46+
with tempfile.NamedTemporaryFile(delete=False) as tf:
47+
fname = tf.name
48+
try:
49+
export_all_variables(self.workspace, self.repo_slug, self.deployment_name, fname, self.auth, self.logger)
50+
with open(fname) as f:
51+
data = json.load(f)
52+
self.assertEqual(len(data), 2)
53+
test_var = next(v for v in data if v["key"] == "A")
54+
self.assertEqual(test_var["value"], "1")
55+
self.assertFalse(test_var["secured"])
56+
secure_var = next(v for v in data if v["key"] == "B")
57+
self.assertEqual(secure_var["value"], "")
58+
self.assertTrue(secure_var["secured"])
59+
finally:
60+
os.unlink(fname)
61+
62+
@patch('manage_bitbucket_env.get_environment_uuid')
63+
@patch('manage_bitbucket_env.get_variables')
64+
def test_export_secure_keys(self, mock_get_vars, mock_get_uuid):
65+
mock_get_uuid.return_value = self.env_uuid
66+
mock_get_vars.return_value = [
67+
{"key": "A", "secured": False},
68+
{"key": "B", "secured": True},
69+
{"key": "C", "secured": True}
70+
]
71+
with tempfile.NamedTemporaryFile(delete=False) as tf:
72+
fname = tf.name
73+
try:
74+
export_secure_keys(self.workspace, self.repo_slug, self.deployment_name, fname, self.auth, self.logger)
75+
with open(fname) as f:
76+
data = json.load(f)
77+
self.assertIn("B", data)
78+
self.assertIn("C", data)
79+
self.assertNotIn("A", data)
80+
finally:
81+
os.unlink(fname)
82+
83+
@patch('manage_bitbucket_env.get_environment_uuid')
84+
@patch('manage_bitbucket_env.get_variables')
85+
@patch('manage_bitbucket_env.update_vars')
86+
def test_import_variables(self, mock_update, mock_get_vars, mock_get_uuid):
87+
mock_get_uuid.return_value = self.env_uuid
88+
mock_get_vars.return_value = []
89+
test_vars = [
90+
{"key": "A", "value": "1", "secured": False},
91+
{"key": "B", "value": "2", "secured": True}
92+
]
93+
with tempfile.NamedTemporaryFile(delete=False, mode='w') as tf:
94+
json.dump(test_vars, tf)
95+
fname = tf.name
96+
try:
97+
import_variables(self.workspace, self.repo_slug, self.deployment_name, fname, False, self.auth, self.logger)
98+
self.assertEqual(mock_update.call_count, 1)
99+
call_args = mock_update.call_args[1]
100+
self.assertEqual(call_args['var']["key"], "A")
101+
finally:
102+
os.unlink(fname)
103+
104+
if __name__ == '__main__':
105+
unittest.main()

tests/test_main.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import unittest
2+
from unittest.mock import patch, Mock
3+
import sys
4+
import os
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
from manage_bitbucket_env import main
7+
8+
class TestMainFunction(unittest.TestCase):
9+
def setUp(self):
10+
self.mock_logger = Mock()
11+
12+
@patch('manage_bitbucket_env.arg_parser')
13+
@patch('manage_bitbucket_env.load_dotenv')
14+
@patch('os.environ.get')
15+
@patch('manage_bitbucket_env.HTTPBasicAuth')
16+
@patch('manage_bitbucket_env.export_variables')
17+
def test_main_export_variables(self, mock_export, mock_auth, mock_env_get, mock_load_dotenv, mock_arg_parser):
18+
mock_args = Mock()
19+
mock_args.output = 'test_output.json'
20+
mock_args.workspace = 'test-workspace'
21+
mock_args.repo_slug = 'test-repo'
22+
mock_args.deployment_name = 'test-deployment'
23+
mock_arg_parser.return_value = mock_args
24+
mock_env_get.side_effect = lambda x: {
25+
'BITBUCKET_USERNAME': 'test_user',
26+
'BITBUCKET_APP_PASSWORD': 'test_password'
27+
}.get(x)
28+
mock_auth_instance = Mock()
29+
mock_auth.return_value = mock_auth_instance
30+
main(self.mock_logger)
31+
mock_export.assert_called_once_with(
32+
workspace='test-workspace',
33+
repo_slug='test-repo',
34+
deployment_name='test-deployment',
35+
output_file='test_output.json',
36+
auth=mock_auth_instance,
37+
logger=self.mock_logger
38+
)
39+
40+
@patch('manage_bitbucket_env.arg_parser')
41+
@patch('manage_bitbucket_env.load_dotenv')
42+
@patch('os.environ.get')
43+
def test_main_missing_credentials(self, mock_env_get, mock_load_dotenv, mock_arg_parser):
44+
mock_args = Mock()
45+
mock_args.output = 'test_output.json'
46+
mock_arg_parser.return_value = mock_args
47+
mock_env_get.return_value = None
48+
with self.assertRaises(SystemExit):
49+
main(self.mock_logger)
50+
51+
if __name__ == '__main__':
52+
unittest.main()

tests/test_update_vars.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import unittest
2+
from unittest.mock import patch, Mock
3+
import sys
4+
import os
5+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
6+
from manage_bitbucket_env import update_vars
7+
8+
class TestUpdateVars(unittest.TestCase):
9+
def setUp(self):
10+
self.logger = Mock()
11+
self.auth = Mock()
12+
self.workspace = 'ws'
13+
self.repo_slug = 'repo'
14+
self.env_uuid = 'uuid-123'
15+
16+
@patch('manage_bitbucket_env.requests.put')
17+
def test_update_existing(self, mock_put):
18+
mock_resp = Mock()
19+
mock_resp.raise_for_status.return_value = None
20+
mock_put.return_value = mock_resp
21+
existing_vars = [{"key": "A", "uuid": "u1", "value": "old", "secured": False}]
22+
new_var = {"key": "A", "value": "new", "secured": False}
23+
update_vars(self.workspace, self.repo_slug, self.env_uuid, existing_vars, new_var, self.auth, self.logger)
24+
mock_put.assert_called_once()
25+
call_args = mock_put.call_args
26+
self.assertIn("u1", call_args[0][0])
27+
28+
@patch('manage_bitbucket_env.requests.post')
29+
def test_update_new(self, mock_post):
30+
mock_resp = Mock()
31+
mock_resp.raise_for_status.return_value = None
32+
mock_post.return_value = mock_resp
33+
existing_vars = []
34+
new_var = {"key": "B", "value": "val", "secured": False}
35+
update_vars(self.workspace, self.repo_slug, self.env_uuid, existing_vars, new_var, self.auth, self.logger)
36+
mock_post.assert_called_once()
37+
38+
if __name__ == '__main__':
39+
unittest.main()

0 commit comments

Comments
 (0)