|
1 | 1 | """Tests for keras_remote.cli.prerequisites_check — tool availability checks.""" |
2 | 2 |
|
| 3 | +from unittest import mock |
| 4 | + |
3 | 5 | import click |
4 | | -import pytest |
| 6 | +from absl.testing import absltest, parameterized |
5 | 7 |
|
6 | 8 | from keras_remote.cli.prerequisites_check import ( |
7 | 9 | check_docker, |
|
12 | 14 | ) |
13 | 15 |
|
14 | 16 |
|
15 | | -@pytest.mark.parametrize( |
16 | | - ("check_fn", "error_match"), |
17 | | - [ |
18 | | - (check_gcloud, "gcloud CLI not found"), |
19 | | - (check_pulumi, "Pulumi CLI not found"), |
20 | | - (check_kubectl, "kubectl not found"), |
21 | | - (check_docker, "Docker not found"), |
22 | | - ], |
23 | | - ids=["gcloud", "pulumi", "kubectl", "docker"], |
24 | | -) |
25 | | -class TestToolChecks: |
26 | | - def test_present(self, mocker, check_fn, error_match): |
27 | | - mocker.patch("shutil.which", return_value="/usr/bin/tool") |
28 | | - check_fn() |
| 17 | +class TestToolChecks(parameterized.TestCase): |
| 18 | + @parameterized.named_parameters( |
| 19 | + dict( |
| 20 | + testcase_name="gcloud", |
| 21 | + check_fn=check_gcloud, |
| 22 | + error_match="gcloud CLI not found", |
| 23 | + ), |
| 24 | + dict( |
| 25 | + testcase_name="pulumi", |
| 26 | + check_fn=check_pulumi, |
| 27 | + error_match="Pulumi CLI not found", |
| 28 | + ), |
| 29 | + dict( |
| 30 | + testcase_name="kubectl", |
| 31 | + check_fn=check_kubectl, |
| 32 | + error_match="kubectl not found", |
| 33 | + ), |
| 34 | + dict( |
| 35 | + testcase_name="docker", |
| 36 | + check_fn=check_docker, |
| 37 | + error_match="Docker not found", |
| 38 | + ), |
| 39 | + ) |
| 40 | + def test_present(self, check_fn, error_match): |
| 41 | + with mock.patch("shutil.which", return_value="/usr/bin/tool"): |
| 42 | + check_fn() |
29 | 43 |
|
30 | | - def test_missing(self, mocker, check_fn, error_match): |
31 | | - mocker.patch("shutil.which", return_value=None) |
32 | | - with pytest.raises(click.ClickException, match=error_match): |
| 44 | + @parameterized.named_parameters( |
| 45 | + dict( |
| 46 | + testcase_name="gcloud", |
| 47 | + check_fn=check_gcloud, |
| 48 | + error_match="gcloud CLI not found", |
| 49 | + ), |
| 50 | + dict( |
| 51 | + testcase_name="pulumi", |
| 52 | + check_fn=check_pulumi, |
| 53 | + error_match="Pulumi CLI not found", |
| 54 | + ), |
| 55 | + dict( |
| 56 | + testcase_name="kubectl", |
| 57 | + check_fn=check_kubectl, |
| 58 | + error_match="kubectl not found", |
| 59 | + ), |
| 60 | + dict( |
| 61 | + testcase_name="docker", |
| 62 | + check_fn=check_docker, |
| 63 | + error_match="Docker not found", |
| 64 | + ), |
| 65 | + ) |
| 66 | + def test_missing(self, check_fn, error_match): |
| 67 | + with ( |
| 68 | + mock.patch("shutil.which", return_value=None), |
| 69 | + self.assertRaisesRegex(click.ClickException, error_match), |
| 70 | + ): |
33 | 71 | check_fn() |
34 | 72 |
|
35 | 73 |
|
36 | | -class TestCheckGcloudAuth: |
37 | | - def test_token_success(self, mocker): |
| 74 | +class TestCheckGcloudAuth(absltest.TestCase): |
| 75 | + def test_token_success(self): |
38 | 76 | """When print-access-token succeeds, no login is triggered.""" |
39 | | - mock_run = mocker.patch( |
| 77 | + with mock.patch( |
40 | 78 | "keras_remote.cli.prerequisites_check.subprocess.run", |
41 | | - ) |
42 | | - mock_run.return_value.returncode = 0 |
43 | | - |
44 | | - check_gcloud_auth() |
| 79 | + ) as mock_run: |
| 80 | + mock_run.return_value.returncode = 0 |
| 81 | + check_gcloud_auth() |
| 82 | + # Only called once (the token check), not a second time for login |
| 83 | + self.assertEqual(mock_run.call_count, 1) |
45 | 84 |
|
46 | | - # Only called once (the token check), not a second time for login |
47 | | - assert mock_run.call_count == 1 |
48 | | - |
49 | | - def test_token_failure_triggers_login(self, mocker): |
| 85 | + def test_token_failure_triggers_login(self): |
50 | 86 | """When print-access-token fails, gcloud auth login is run.""" |
51 | | - mock_run = mocker.patch( |
52 | | - "keras_remote.cli.prerequisites_check.subprocess.run", |
53 | | - ) |
54 | | - # First call = token check (fails), second call = login (succeeds) |
55 | | - token_result = mocker.MagicMock() |
56 | | - token_result.returncode = 1 |
57 | | - mock_run.return_value = token_result |
| 87 | + with ( |
| 88 | + mock.patch( |
| 89 | + "keras_remote.cli.prerequisites_check.subprocess.run", |
| 90 | + ) as mock_run, |
| 91 | + mock.patch("keras_remote.cli.prerequisites_check.warning"), |
| 92 | + mock.patch("click.echo"), |
| 93 | + ): |
| 94 | + token_result = mock.MagicMock() |
| 95 | + token_result.returncode = 1 |
| 96 | + mock_run.return_value = token_result |
| 97 | + |
| 98 | + check_gcloud_auth() |
58 | 99 |
|
59 | | - mocker.patch("keras_remote.cli.prerequisites_check.warning") |
60 | | - mocker.patch("click.echo") |
| 100 | + self.assertEqual(mock_run.call_count, 2) |
| 101 | + # Second call should be the login command |
| 102 | + login_call = mock_run.call_args_list[1] |
| 103 | + self.assertIn("login", login_call[0][0]) |
61 | 104 |
|
62 | | - check_gcloud_auth() |
63 | 105 |
|
64 | | - assert mock_run.call_count == 2 |
65 | | - # Second call should be the login command |
66 | | - login_call = mock_run.call_args_list[1] |
67 | | - assert "login" in login_call[0][0] |
| 106 | +if __name__ == "__main__": |
| 107 | + absltest.main() |
0 commit comments