11"""Unit tests for the iterations feature."""
22
3+ from unittest .mock import MagicMock , create_autospec , patch
4+
35import pytest
4- from unittest .mock import MagicMock , patch , create_autospec
56from grasshopper .lib .grasshopper import Grasshopper
67from grasshopper .lib .journeys .base_journey import BaseJourney
78from locust .env import Environment
9+ from locust .exception import StopUser
810from locust .runners import LocalRunner
911from locust .user .task import DefaultTaskSet , TaskSet
10- from locust .exception import StopUser
1112
1213
1314class MockJourney (BaseJourney ):
1415 """Mock journey for testing."""
15-
16+
1617 def __init__ (self , * args , ** kwargs ):
1718 super ().__init__ (* args , ** kwargs )
1819 self .task_count = 0
19-
20+
2021 def example_task (self ):
2122 self .task_count += 1
2223
@@ -35,24 +36,24 @@ def mock_environment():
3536def test_setup_iteration_limit_initializes_runner_attributes (mock_environment ):
3637 """Test that _setup_iteration_limit properly initializes runner attributes."""
3738 Grasshopper ._setup_iteration_limit (mock_environment , 10 )
38-
39+
3940 assert mock_environment .runner .iterations_started == 0
40- assert mock_environment .runner .iteration_target_reached == False
41+ assert mock_environment .runner .iteration_target_reached is False
4142
4243
4344def test_setup_iteration_limit_patches_taskset_methods (mock_environment ):
4445 """Test that _setup_iteration_limit patches TaskSet methods."""
4546 # Store original methods
4647 original_taskset_execute = TaskSet .execute_task
4748 original_default_taskset_execute = DefaultTaskSet .execute_task
48-
49+
4950 try :
5051 Grasshopper ._setup_iteration_limit (mock_environment , 10 )
51-
52+
5253 # Check that methods have been patched (wrapped)
5354 assert TaskSet .execute_task != original_taskset_execute
5455 assert DefaultTaskSet .execute_task != original_default_taskset_execute
55-
56+
5657 finally :
5758 # Restore original methods
5859 TaskSet .execute_task = original_taskset_execute
@@ -63,104 +64,98 @@ def test_iteration_limit_stops_after_reaching_limit(mock_environment):
6364 """Test that tasks stop executing after iteration limit is reached."""
6465 # Store original method
6566 original_taskset_execute = TaskSet .execute_task
66-
67+
6768 try :
6869 Grasshopper ._setup_iteration_limit (mock_environment , 2 )
69-
70+
7071 # Create a mock TaskSet
7172 mock_taskset = MagicMock (spec = TaskSet )
7273 mock_task = MagicMock ()
73-
74+
7475 # Execute tasks up to the limit
7576 TaskSet .execute_task (mock_taskset , mock_task )
7677 assert mock_environment .runner .iterations_started == 1
77-
78+
7879 TaskSet .execute_task (mock_taskset , mock_task )
7980 assert mock_environment .runner .iterations_started == 2
80-
81+
8182 # Next execution should raise StopUser
8283 with pytest .raises (StopUser ):
8384 TaskSet .execute_task (mock_taskset , mock_task )
84-
85+
8586 # Verify that iteration target was reached
86- assert mock_environment .runner .iteration_target_reached == True
87-
87+ assert mock_environment .runner .iteration_target_reached is True
88+
8889 finally :
8990 # Restore original method
9091 TaskSet .execute_task = original_taskset_execute
9192
9293
9394def test_launch_test_with_iterations_no_runtime_timer ():
9495 """Test that launch_test doesn't set runtime timer when iterations is specified."""
95- with patch .object (Grasshopper , 'set_ulimit' ), \
96- patch .object (Grasshopper , '_setup_iteration_limit' ) as mock_setup_iterations , \
97- patch ('grasshopper.lib.grasshopper.Environment' ) as MockEnvironment , \
98- patch ('grasshopper.lib.grasshopper.gevent.spawn_later' ) as mock_spawn_later , \
99- patch ('grasshopper.lib.grasshopper.gevent.spawn' ), \
100- patch ('grasshopper.lib.grasshopper.locust.stats.stats_history' ), \
101- patch ('grasshopper.lib.grasshopper.GrasshopperListeners' ):
102-
96+ with patch .object (Grasshopper , "set_ulimit" ), patch .object (
97+ Grasshopper , "_setup_iteration_limit"
98+ ) as mock_setup_iterations , patch (
99+ "grasshopper.lib.grasshopper.Environment"
100+ ) as MockEnvironment , patch (
101+ "grasshopper.lib.grasshopper.gevent.spawn_later"
102+ ) as mock_spawn_later , patch ("grasshopper.lib.grasshopper.gevent.spawn" ), patch (
103+ "grasshopper.lib.grasshopper.locust.stats.stats_history"
104+ ), patch ("grasshopper.lib.grasshopper.GrasshopperListeners" ):
103105 # Setup mock environment
104106 mock_env = MagicMock ()
105107 mock_env .runner = MagicMock ()
106108 mock_env .runner .greenlet = MagicMock ()
107109 mock_env .runner .greenlet .join = MagicMock ()
108110 MockEnvironment .return_value = mock_env
109-
111+
110112 # Mock shape instance
111113 mock_shape = MagicMock ()
112114 mock_shape .configured_runtime = 120
113-
115+
114116 # Launch test with iterations
115- kwargs = {
116- 'iterations' : 10 ,
117- 'runtime' : 120 ,
118- 'shape_instance' : mock_shape
119- }
120-
117+ kwargs = {"iterations" : 10 , "runtime" : 120 , "shape_instance" : mock_shape }
118+
121119 Grasshopper .launch_test (MockJourney , ** kwargs )
122-
120+
123121 # Verify that _setup_iteration_limit was called
124122 mock_setup_iterations .assert_called_once_with (mock_env , 10 )
125-
123+
126124 # Verify that runtime timer was NOT set (spawn_later not called)
127125 mock_spawn_later .assert_not_called ()
128126
129127
130128def test_launch_test_without_iterations_sets_runtime_timer ():
131129 """Test that launch_test sets runtime timer when iterations is not specified."""
132- with patch .object (Grasshopper , 'set_ulimit' ), \
133- patch .object (Grasshopper , '_setup_iteration_limit' ) as mock_setup_iterations , \
134- patch ('grasshopper.lib.grasshopper.Environment' ) as MockEnvironment , \
135- patch ('grasshopper.lib.grasshopper.gevent.spawn_later' ) as mock_spawn_later , \
136- patch ('grasshopper.lib.grasshopper.gevent.spawn' ), \
137- patch ('grasshopper.lib.grasshopper.locust.stats.stats_history' ), \
138- patch ('grasshopper.lib.grasshopper.GrasshopperListeners' ):
139-
130+ with patch .object (Grasshopper , "set_ulimit" ), patch .object (
131+ Grasshopper , "_setup_iteration_limit"
132+ ) as mock_setup_iterations , patch (
133+ "grasshopper.lib.grasshopper.Environment"
134+ ) as MockEnvironment , patch (
135+ "grasshopper.lib.grasshopper.gevent.spawn_later"
136+ ) as mock_spawn_later , patch ("grasshopper.lib.grasshopper.gevent.spawn" ), patch (
137+ "grasshopper.lib.grasshopper.locust.stats.stats_history"
138+ ), patch ("grasshopper.lib.grasshopper.GrasshopperListeners" ):
140139 # Setup mock environment
141140 mock_env = MagicMock ()
142141 mock_env .runner = MagicMock ()
143142 mock_env .runner .greenlet = MagicMock ()
144143 mock_env .runner .greenlet .join = MagicMock ()
145144 MockEnvironment .return_value = mock_env
146-
145+
147146 # Mock shape instance
148147 mock_shape = MagicMock ()
149148 mock_shape .configured_runtime = 120
150-
149+
151150 # Launch test without iterations (or with 0)
152- kwargs = {
153- 'iterations' : 0 ,
154- 'runtime' : 120 ,
155- 'shape_instance' : mock_shape
156- }
157-
151+ kwargs = {"iterations" : 0 , "runtime" : 120 , "shape_instance" : mock_shape }
152+
158153 Grasshopper .launch_test (MockJourney , ** kwargs )
159-
154+
160155 # Verify that _setup_iteration_limit was NOT called
161156 mock_setup_iterations .assert_not_called ()
162-
157+
163158 # Verify that runtime timer WAS set
164159 mock_spawn_later .assert_called_once ()
165160 # Check that it was called with the runtime value
166- assert mock_spawn_later .call_args [0 ][0 ] == 120
161+ assert mock_spawn_later .call_args [0 ][0 ] == 120
0 commit comments