1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15- import os
16- import pytest
1715import json
1816import logging
17+ import os
1918import subprocess
19+ from unittest .mock import MagicMock , mock_open
2020
21- from unittest . mock import mock_open , MagicMock
21+ import pytest
2222
2323from cli import (
24- _read_json_file ,
25- _determine_bazel_rule ,
24+ GENERATE_REQUEST_FILE ,
25+ LIBRARIAN_DIR ,
26+ REPO_DIR ,
2627 _build_bazel_target ,
28+ _determine_bazel_rule ,
29+ _get_library_id ,
2730 _locate_and_extract_artifact ,
28- handle_generate ,
31+ _read_json_file ,
32+ _run_individual_session ,
33+ _run_nox_sessions ,
2934 handle_build ,
3035 handle_configure ,
31- LIBRARIAN_DIR ,
32- GENERATE_REQUEST_FILE ,
36+ handle_generate ,
3337)
3438
3539
@@ -53,6 +57,42 @@ def mock_generate_request_file(tmp_path, monkeypatch):
5357 return request_file
5458
5559
60+ @pytest .fixture
61+ def mock_generate_request_data_for_nox ():
62+ """Returns mock data for generate-request.json for nox tests."""
63+ return {
64+ "id" : "mock-library" ,
65+ "apis" : [
66+ {"path" : "google/mock/v1" },
67+ ],
68+ }
69+
70+
71+ def test_get_library_id_success ():
72+ """Tests that _get_library_id returns the correct ID when present."""
73+ request_data = {"id" : "test-library" , "name" : "Test Library" }
74+ library_id = _get_library_id (request_data )
75+ assert library_id == "test-library"
76+
77+
78+ def test_get_library_id_missing_id ():
79+ """Tests that _get_library_id raises ValueError when 'id' is missing."""
80+ request_data = {"name" : "Test Library" }
81+ with pytest .raises (
82+ ValueError , match = "Request file is missing required 'id' field."
83+ ):
84+ _get_library_id (request_data )
85+
86+
87+ def test_get_library_id_empty_id ():
88+ """Tests that _get_library_id raises ValueError when 'id' is an empty string."""
89+ request_data = {"id" : "" , "name" : "Test Library" }
90+ with pytest .raises (
91+ ValueError , match = "Request file is missing required 'id' field."
92+ ):
93+ _get_library_id (request_data )
94+
95+
5696def test_handle_configure_success (caplog , mock_generate_request_file ):
5797 """
5898 Tests the successful execution path of handle_configure.
@@ -191,12 +231,105 @@ def test_handle_generate_fail(caplog):
191231 handle_generate ()
192232
193233
194- def test_handle_build_success (caplog , mock_generate_request_file ):
234+ def test_run_individual_session_success (mocker , caplog ):
235+ """Tests that _run_individual_session calls nox with correct arguments and logs success."""
236+ caplog .set_level (logging .INFO )
237+
238+ mock_subprocess_run = mocker .patch (
239+ "cli.subprocess.run" , return_value = MagicMock (returncode = 0 )
240+ )
241+
242+ test_session = "unit-3.9"
243+ test_library_id = "test-library"
244+ _run_individual_session (test_session , test_library_id )
245+
246+ expected_command = [
247+ "nox" ,
248+ "-s" ,
249+ test_session ,
250+ "-f" ,
251+ f"{ REPO_DIR } /packages/{ test_library_id } " ,
252+ ]
253+ mock_subprocess_run .assert_called_once_with (expected_command , text = True , check = True )
254+
255+
256+ def test_run_individual_session_failure (mocker ):
257+ """Tests that _run_individual_session raises CalledProcessError if nox command fails."""
258+ mocker .patch (
259+ "cli.subprocess.run" ,
260+ side_effect = subprocess .CalledProcessError (
261+ 1 , "nox" , stderr = "Nox session failed"
262+ ),
263+ )
264+
265+ with pytest .raises (subprocess .CalledProcessError ):
266+ _run_individual_session ("lint" , "another-library" )
267+
268+
269+ def test_run_nox_sessions_success (mocker , mock_generate_request_data_for_nox ):
270+ """Tests that _run_nox_sessions successfully runs all specified sessions."""
271+ mocker .patch ("cli._read_json_file" , return_value = mock_generate_request_data_for_nox )
272+ mocker .patch ("cli._get_library_id" , return_value = "mock-library" )
273+ mock_run_individual_session = mocker .patch ("cli._run_individual_session" )
274+
275+ sessions_to_run = ["unit-3.9" , "lint" ]
276+ _run_nox_sessions (sessions_to_run )
277+
278+ assert mock_run_individual_session .call_count == len (sessions_to_run )
279+ mock_run_individual_session .assert_has_calls (
280+ [
281+ mocker .call ("unit-3.9" , "mock-library" ),
282+ mocker .call ("lint" , "mock-library" ),
283+ ]
284+ )
285+
286+
287+ def test_run_nox_sessions_read_file_failure (mocker ):
288+ """Tests that _run_nox_sessions raises ValueError if _read_json_file fails."""
289+ mocker .patch ("cli._read_json_file" , side_effect = FileNotFoundError ("file not found" ))
290+
291+ with pytest .raises (ValueError , match = "Failed to run the nox session" ):
292+ _run_nox_sessions (["unit-3.9" ])
293+
294+
295+ def test_run_nox_sessions_get_library_id_failure (mocker ):
296+ """Tests that _run_nox_sessions raises ValueError if _get_library_id fails."""
297+ mocker .patch ("cli._read_json_file" , return_value = {"apis" : []}) # Missing 'id'
298+ mocker .patch (
299+ "cli._get_library_id" ,
300+ side_effect = ValueError ("Request file is missing required 'id' field." ),
301+ )
302+
303+ with pytest .raises (ValueError , match = "Failed to run the nox session" ):
304+ _run_nox_sessions (["unit-3.9" ])
305+
306+
307+ def test_run_nox_sessions_individual_session_failure (
308+ mocker , mock_generate_request_data_for_nox
309+ ):
310+ """Tests that _run_nox_sessions raises ValueError if _run_individual_session fails."""
311+ mocker .patch ("cli._read_json_file" , return_value = mock_generate_request_data_for_nox )
312+ mocker .patch ("cli._get_library_id" , return_value = "mock-library" )
313+ mock_run_individual_session = mocker .patch (
314+ "cli._run_individual_session" ,
315+ side_effect = [None , subprocess .CalledProcessError (1 , "nox" , "session failed" )],
316+ )
317+
318+ sessions_to_run = ["unit-3.9" , "lint" ]
319+ with pytest .raises (ValueError , match = "Failed to run the nox session" ):
320+ _run_nox_sessions (sessions_to_run )
321+
322+ # Check that _run_individual_session was called at least once
323+ assert mock_run_individual_session .call_count > 0
324+
325+
326+ def test_handle_build_success (caplog , mocker ):
195327 """
196328 Tests the successful execution path of handle_build.
197329 """
198330 caplog .set_level (logging .INFO )
199331
332+ mocker .patch ("cli._run_nox_sessions" )
200333 handle_build ()
201334
202335 assert "'build' command executed." in caplog .text
0 commit comments