Skip to content

Commit 87b9972

Browse files
sandeepthalapananedremdemgpsaggese
authored
HelpersTask615_Come_up_with_a_testing_approach_for_release_flow (#651)
* HelpersTask615: Add unittest for docker_build_local_image() Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Modify comments and docstring Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Move helper functions out of the class Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Rename helper functions Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Split the check into seperate checks Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Remove .body from function call Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * Update Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Propogate changes from previous commit Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Modify comments Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Added tests for building prod_image Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Add a helper test class to refactor common code Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Move inputs into setUp Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ * HelpersTask615: Change setUp and tearDown Pre-commit checks: - 'check_master' passed - 'check_author' passed - 'check_file_size' passed - 'check_python_compile' passed - 'check_gitleaks' passed All checks passed ✅ --------- Co-authored-by: Vlad <[email protected]> Co-authored-by: GP Saggese <[email protected]> Co-authored-by: GP Saggese <[email protected]>
1 parent c7a9c57 commit 87b9972

File tree

1 file changed

+220
-56
lines changed

1 file changed

+220
-56
lines changed

helpers/test/test_lib_tasks_docker_release.py

Lines changed: 220 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import logging
22
import unittest.mock as umock
3-
from typing import List
3+
from typing import Generator, List
4+
5+
import pytest
46

5-
import helpers.hsystem as hsystem
67
import helpers.hunit_test as hunitest
78
import helpers.lib_tasks_docker_release as hltadore
89
import helpers.test.test_lib_tasks as httestlib
@@ -36,17 +37,23 @@ def _extract_commands_from_call(calls: List[umock._Call]) -> List[str]:
3637

3738

3839
# #############################################################################
39-
# TestDockerBuildLocalImage1
40+
# _DockerFlowTestHelper
4041
# #############################################################################
4142

4243

43-
class TestDockerBuildLocalImage1(hunitest.TestCase):
44+
class _DockerFlowTestHelper(hunitest.TestCase):
45+
"""
46+
Helper test class to perform common setup, teardown logic and assertion
47+
checks for Docker flow tests.
48+
"""
4449

45-
def setUp(self) -> None:
46-
"""
47-
Set up test environment and initialize all necessary mocks.
48-
"""
49-
super().setUp()
50+
@pytest.fixture(autouse=True)
51+
def setup_teardown_test(self) -> Generator:
52+
self.set_up_test()
53+
yield
54+
self.tear_down_test()
55+
56+
def set_up_test(self) -> None:
5057
# Mock system calls.
5158
self.system_patcher = umock.patch("helpers.hsystem.system")
5259
self.mock_system = self.system_patcher.start()
@@ -63,41 +70,78 @@ def setUp(self) -> None:
6370
"helpers.lib_tasks_docker.docker_login"
6471
)
6572
self.mock_docker_login = self.docker_login_patcher.start()
73+
# Mock environment variable.
74+
self.env_patcher = umock.patch.dict(
75+
"os.environ", {"CSFY_ECR_BASE_PATH": "test.ecr.path"}
76+
)
77+
self.env_patcher.start()
6678
#
67-
self.user = hsystem.get_user_name()
79+
self.patchers = [
80+
self.system_patcher,
81+
self.run_patcher,
82+
self.version_patcher,
83+
self.docker_login_patcher,
84+
self.env_patcher,
85+
]
86+
# Test inputs.
87+
self.mock_ctx = httestlib._build_mock_context_returning_ok()
88+
self.test_version = "1.0.0"
89+
self.test_base_image = "test-registry.com/test-image"
90+
self.test_multi_arch = "linux/amd64,linux/arm64"
6891

69-
def tearDown(self) -> None:
92+
def tear_down_test(self) -> None:
7093
"""
7194
Clean up test environment by stopping all mocks after each test case.
7295
"""
73-
self.system_patcher.stop()
74-
self.run_patcher.stop()
75-
self.version_patcher.stop()
76-
self.docker_login_patcher.stop()
77-
super().tearDown()
96+
for patcher in self.patchers:
97+
patcher.stop()
98+
99+
def _check_docker_command_output(
100+
self, exp: str, call_args_list: List[umock._Call]
101+
) -> None:
102+
"""
103+
Check that the sequence of commands from mock calls matches the
104+
expected string.
105+
106+
:param exp: expected command string
107+
:param call_args_list: list of mock call objects
108+
"""
109+
actual_cmds = _extract_commands_from_call(call_args_list)
110+
actual_cmds = "\n".join(actual_cmds)
111+
self.assert_equal(
112+
actual_cmds,
113+
exp,
114+
purify_text=True,
115+
purify_expected_text=True,
116+
fuzzy_match=True,
117+
remove_lead_trail_empty_lines=True,
118+
dedent=True,
119+
)
78120

79-
def test_docker_build_single_arch(self) -> None:
121+
122+
# #############################################################################
123+
# Test_docker_build_local_image1
124+
# #############################################################################
125+
126+
127+
class Test_docker_build_local_image1(_DockerFlowTestHelper):
128+
129+
def test_docker_build_local_image_single_arch(self) -> None:
80130
"""
81131
Test building a local Docker image with single architecture.
82132
83133
This test verifies that the correct sequence of commands is
84134
generated for building a local Docker image with single
85135
architecture.
86136
"""
87-
# Prepare inputs.
88-
mock_ctx = httestlib._build_mock_context_returning_ok()
89-
test_version = "1.0.0"
90-
test_base_image = "test-registry.com/test-image"
91137
# Call tested function.
92138
hltadore.docker_build_local_image(
93-
mock_ctx,
94-
test_version,
139+
self.mock_ctx,
140+
self.test_version,
95141
cache=False,
96-
base_image=test_base_image,
142+
base_image=self.test_base_image,
97143
poetry_mode="update",
98144
)
99-
actual_cmds = _extract_commands_from_call(self.mock_run.call_args_list)
100-
actual_cmds = "\n".join(actual_cmds)
101145
# The output is a list of strings, each representing a command.
102146
exp = r"""
103147
cp -f devops/docker_build/dockerignore.dev .dockerignore
@@ -114,41 +158,25 @@ def test_docker_build_single_arch(self) -> None:
114158
cp -f pip_list.txt ./devops/docker_build/pip_list.txt
115159
docker image ls test-registry.com/test-image:local-$USER_NAME-1.0.0
116160
"""
117-
# Check output.
118-
self.assert_equal(
119-
actual_cmds,
120-
exp,
121-
purify_text=True,
122-
fuzzy_match=True,
123-
remove_lead_trail_empty_lines=True,
124-
dedent=True,
125-
)
161+
self._check_docker_command_output(exp, self.mock_run.call_args_list)
126162

127-
def test_docker_build_multi_arch(self) -> None:
163+
def test_docker_build_local_image_multi_arch(self) -> None:
128164
"""
129165
Test building a local Docker image with multiple architectures.
130166
131167
This test verifies that the correct sequence of commands is
132168
generated for building a local Docker image with multiple
133169
architectures.
134170
"""
135-
# Prepare inputs.
136-
mock_ctx = httestlib._build_mock_context_returning_ok()
137-
test_version = "1.0.0"
138-
test_base_image = "test-registry.com/test-image"
139-
test_multi_arch = "linux/amd64,linux/arm64"
140171
# Call tested function.
141172
hltadore.docker_build_local_image(
142-
mock_ctx,
143-
test_version,
173+
self.mock_ctx,
174+
self.test_version,
144175
cache=False,
145-
base_image=test_base_image,
176+
base_image=self.test_base_image,
146177
poetry_mode="update",
147-
multi_arch=test_multi_arch,
178+
multi_arch=self.test_multi_arch,
148179
)
149-
actual_cmds = _extract_commands_from_call(self.mock_run.call_args_list)
150-
actual_cmds = "\n".join(actual_cmds)
151-
# The output is a list of strings, each representing a command.
152180
exp = r"""
153181
cp -f devops/docker_build/dockerignore.dev .dockerignore
154182
docker buildx create \
@@ -173,12 +201,148 @@ def test_docker_build_multi_arch(self) -> None:
173201
cp -f pip_list.txt ./devops/docker_build/pip_list.txt
174202
docker image ls test-registry.com/test-image:local-$USER_NAME-1.0.0
175203
"""
176-
# Check output.
177-
self.assert_equal(
178-
actual_cmds,
179-
exp,
180-
purify_text=True,
181-
fuzzy_match=True,
182-
remove_lead_trail_empty_lines=True,
183-
dedent=True,
204+
self._check_docker_command_output(exp, self.mock_run.call_args_list)
205+
206+
207+
# #############################################################################
208+
# Test_docker_build_prod_image1
209+
# #############################################################################
210+
211+
212+
class Test_docker_build_prod_image1(_DockerFlowTestHelper):
213+
214+
def test_docker_build_prod_image(self) -> None:
215+
"""
216+
Test building a prod Docker image with single architecture.
217+
218+
This test verifies that the correct sequence of commands is
219+
generated for building a prod Docker image.
220+
"""
221+
# Call tested function.
222+
hltadore.docker_build_prod_image(
223+
self.mock_ctx,
224+
self.test_version,
225+
base_image=self.test_base_image,
226+
cache=False,
227+
)
228+
exp = r"""
229+
cp -f devops/docker_build/dockerignore.prod .dockerignore
230+
DOCKER_BUILDKIT=0 \
231+
time \
232+
docker build \
233+
--no-cache \
234+
--tag test-registry.com/test-image:prod-1.0.0 \
235+
--file /app/devops/docker_build/prod.Dockerfile \
236+
--build-arg VERSION=1.0.0 \
237+
--build-arg ECR_BASE_PATH=test.ecr.path \
238+
.
239+
docker tag test-registry.com/test-image:prod-1.0.0 test-registry.com/test-image:prod
240+
docker image ls test-registry.com/test-image:prod
241+
"""
242+
self._check_docker_command_output(exp, self.mock_run.call_args_list)
243+
244+
def test_docker_build_multi_arch_prod_image(self) -> None:
245+
"""
246+
Test building a prod Docker image with multiple architectures.
247+
248+
This test verifies that the correct sequence of commands is
249+
generated for building a multi-arch prod Docker image.
250+
"""
251+
# Call tested function.
252+
hltadore.docker_build_multi_arch_prod_image(
253+
self.mock_ctx,
254+
self.test_version,
255+
base_image=self.test_base_image,
256+
cache=False,
257+
multi_arch=self.test_multi_arch,
258+
)
259+
exp = r"""
260+
cp -f devops/docker_build/dockerignore.prod .dockerignore
261+
docker buildx create \
262+
--name multiarch_builder \
263+
--driver docker-container \
264+
--bootstrap \
265+
&& \
266+
docker buildx use multiarch_builder
267+
tar -czh . | DOCKER_BUILDKIT=0 \
268+
time \
269+
docker buildx build \
270+
--no-cache \
271+
--push \
272+
--platform linux/amd64,linux/arm64 \
273+
--build-arg VERSION=1.0.0 --build-arg ECR_BASE_PATH=test.ecr.path \
274+
--tag test-registry.com/test-image:prod-1.0.0 \
275+
--file devops/docker_build/prod.Dockerfile \
276+
-
277+
docker pull test-registry.com/test-image:prod-1.0.0
278+
docker image ls test-registry.com/test-image:prod-1.0.0
279+
"""
280+
self._check_docker_command_output(exp, self.mock_run.call_args_list)
281+
282+
def test_docker_build_prod_image_with_candidate_tag(self) -> None:
283+
"""
284+
Test building a prod Docker image with candidate mode using tag.
285+
286+
This test verifies that the correct sequence of commands is
287+
generated for building a prod image with candidate mode using
288+
tag.
289+
"""
290+
test_tag = "test_tag"
291+
# Call tested function.
292+
hltadore.docker_build_prod_image(
293+
self.mock_ctx,
294+
self.test_version,
295+
base_image=self.test_base_image,
296+
cache=False,
297+
candidate=True,
298+
tag=test_tag,
299+
)
300+
exp = r"""
301+
cp -f devops/docker_build/dockerignore.prod .dockerignore
302+
DOCKER_BUILDKIT=0 \
303+
time \
304+
docker build \
305+
--no-cache \
306+
--tag test-registry.com/test-image:prod-test_tag \
307+
--file /app/devops/docker_build/prod.Dockerfile \
308+
--build-arg VERSION=1.0.0 \
309+
--build-arg ECR_BASE_PATH=test.ecr.path \
310+
.
311+
docker image ls test-registry.com/test-image:prod-test_tag
312+
"""
313+
self._check_docker_command_output(exp, self.mock_run.call_args_list)
314+
315+
def test_docker_build_prod_image_with_candidate_user_tag(self) -> None:
316+
"""
317+
Test building a prod Docker image with candidate mode using user tag.
318+
319+
This test verifies that the correct sequence of commands is
320+
generated for building a prod image with candidate mode using
321+
user tag and tag.
322+
"""
323+
test_user_tag = "test_user"
324+
test_tag = "test_tag"
325+
# Call tested function.
326+
hltadore.docker_build_prod_image(
327+
self.mock_ctx,
328+
self.test_version,
329+
base_image=self.test_base_image,
330+
cache=False,
331+
candidate=True,
332+
user_tag=test_user_tag,
333+
tag=test_tag,
184334
)
335+
exp = r"""
336+
cp -f devops/docker_build/dockerignore.prod .dockerignore
337+
DOCKER_BUILDKIT=0 \
338+
time \
339+
docker build \
340+
--no-cache \
341+
--tag test-registry.com/test-image:prod-test_user-test_tag \
342+
--file /app/devops/docker_build/prod.Dockerfile \
343+
--build-arg VERSION=1.0.0 \
344+
--build-arg ECR_BASE_PATH=test.ecr.path \
345+
.
346+
docker image ls test-registry.com/test-image:prod-test_user-test_tag
347+
"""
348+
self._check_docker_command_output(exp, self.mock_run.call_args_list)

0 commit comments

Comments
 (0)