11import pytest
22from unittest .mock import MagicMock
3- import pytest # Ensure pytest is imported if not already
3+ # pytest is imported twice in the current file, remove one
4+ # import pytest # Ensure pytest is imported if not already
45
56from examples .advanced_operations .get_ad_group_bid_modifiers import main
67
78class MockAdGroupBidModifierModel :
8- def __init__ (self , client_enums_mock ): # Renamed to avoid conflict with client fixture
9- # --- Begin: Attributes accessed directly by the script's print statement or logic ---
9+ def __init__ (self , client_enums_mock ):
1010 self .criterion_id = MagicMock (name = "criterion_id_attr" )
1111 self .bid_modifier = MagicMock (name = "bid_modifier_attr" )
1212
1313 self .device = MagicMock (name = "device_attr" )
14- # Ensure type_ itself is a mock that has a .name attribute
1514 self .device .type_ = MagicMock (name = "device_type_attr" )
16- self .device .type_ .name = "DEFAULT_DEVICE_NAME" # Default .name
15+ self .device .type_ .name = "DEFAULT_DEVICE_NAME"
1716
18- # Hotel criteria attributes (initialize them as MagicMocks)
1917 self .hotel_date_selection_type = MagicMock (name = "hotel_date_selection_type_attr" )
2018 self .hotel_date_selection_type .type_ = MagicMock (name = "hotel_date_selection_type_type_attr" )
2119 self .hotel_date_selection_type .type_ .name = "DEFAULT_HOTEL_DATE_NAME"
2220
23-
2421 self .hotel_advance_booking_window = MagicMock (name = "hotel_advance_booking_window_attr" )
2522 self .hotel_advance_booking_window .min_days = None
2623 self .hotel_advance_booking_window .max_days = None
@@ -37,28 +34,24 @@ def __init__(self, client_enums_mock): # Renamed to avoid conflict with client f
3734 self .hotel_check_in_date_range .start_date = None
3835 self .hotel_check_in_date_range .end_date = None
3936
40- # This will store the name of the 'oneof' criterion field (e.g., "device")
41- self ._active_criterion_field = "device" # Default active field
37+ self ._active_criterion_field = "device"
4238
43- # This class method mimics the real .pb() class method on Google Ads model classes.
4439 @classmethod
4540 def pb (cls , instance_self ):
46- # instance_self here is an instance of MockAdGroupBidModifierModel
4741 mock_pb_message = MagicMock (name = "pb_message_obj_from_class" )
48- # WhichOneof should return the active criterion field name for this instance
4942 mock_pb_message .WhichOneof .return_value = instance_self ._active_criterion_field
5043 return mock_pb_message
5144
52- # Helper to set the active criterion field for testing different types
5345 def set_active_criterion_field (self , field_name_str ):
5446 self ._active_criterion_field = field_name_str
55- # Example: If setting device, ensure device attributes are primary
56- if field_name_str == "device" :
57- # self.device.type_ is already a mock, its .name can be set in test
58- pass
59- # Add similar logic if other criterion types need specific default setup when activated
6047 return self
6148
49+ class MockGoogleAdsRow : # Newly added class
50+ def __init__ (self ):
51+ self .ad_group_bid_modifier = None
52+ self .ad_group = MagicMock (spec = ['id' ])
53+ self .campaign = MagicMock (spec = ['id' ])
54+
6255# --- Test Functions ---
6356def test_main_runs_successfully (mock_google_ads_client : MagicMock ) -> None :
6457 """Tests that the main function runs without raising an exception with an ad_group_id."""
@@ -68,47 +61,40 @@ def test_main_runs_successfully(mock_google_ads_client: MagicMock) -> None:
6861 # --- Mock Enums (ensure they have .name attribute) ---
6962 mock_enums = mock_google_ads_client .enums
7063
71- # DeviceEnum setup
7264 mock_enums .DeviceEnum .MOBILE = MagicMock (name = "DeviceEnum.MOBILE" ); mock_enums .DeviceEnum .MOBILE .name = "MOBILE"
7365 mock_enums .DeviceEnum .TABLET = MagicMock (name = "DeviceEnum.TABLET" ); mock_enums .DeviceEnum .TABLET .name = "TABLET"
7466 mock_enums .DeviceEnum .DESKTOP = MagicMock (name = "DeviceEnum.DESKTOP" ); mock_enums .DeviceEnum .DESKTOP .name = "DESKTOP"
75- mock_enums .DeviceEnum .UNKNOWN = MagicMock (name = "DeviceEnum.UNKNOWN" ); mock_enums .DeviceEnum .UNKNOWN .name = "UNKNOWN_DEVICE_FOR_PRINT" # Default in class constructor matched
67+ mock_enums .DeviceEnum .UNKNOWN = MagicMock (name = "DeviceEnum.UNKNOWN" ); mock_enums .DeviceEnum .UNKNOWN .name = "UNKNOWN_DEVICE_NAME"
7668
77- # HotelDateSelectionTypeEnum setup
7869 mock_enums .HotelDateSelectionTypeEnum .DEFAULT_SELECTION = MagicMock (name = "HotelDateSelectionTypeEnum.DEFAULT_SELECTION" ); mock_enums .HotelDateSelectionTypeEnum .DEFAULT_SELECTION .name = "DEFAULT_SELECTION"
7970 mock_enums .HotelDateSelectionTypeEnum .USER_SELECTED = MagicMock (name = "HotelDateSelectionTypeEnum.USER_SELECTED" ); mock_enums .HotelDateSelectionTypeEnum .USER_SELECTED .name = "USER_SELECTED"
80- mock_enums .HotelDateSelectionTypeEnum .UNKNOWN = MagicMock (name = "HotelDateSelectionTypeEnum.UNKNOWN" ); mock_enums .HotelDateSelectionTypeEnum .UNKNOWN .name = "UNKNOWN_HOTEL_DATE_FOR_PRINT "
71+ mock_enums .HotelDateSelectionTypeEnum .UNKNOWN = MagicMock (name = "HotelDateSelectionTypeEnum.UNKNOWN" ); mock_enums .HotelDateSelectionTypeEnum .UNKNOWN .name = "UNKNOWN_HOTEL_DATE_NAME "
8172
82- # DayOfWeekEnum setup
8373 mock_enums .DayOfWeekEnum .MONDAY = MagicMock (name = "DayOfWeekEnum.MONDAY" ); mock_enums .DayOfWeekEnum .MONDAY .name = "MONDAY"
84- mock_enums .DayOfWeekEnum .UNSPECIFIED = MagicMock (name = "DayOfWeekEnum.UNSPECIFIED" ); mock_enums .DayOfWeekEnum .UNSPECIFIED .name = "UNSPECIFIED_DAY_FOR_PRINT "
74+ mock_enums .DayOfWeekEnum .UNSPECIFIED = MagicMock (name = "DayOfWeekEnum.UNSPECIFIED" ); mock_enums .DayOfWeekEnum .UNSPECIFIED .name = "UNSPECIFIED_DAY_NAME "
8575
8676 # --- Mock GoogleAdsService for search ---
8777 mock_googleads_service = mock_google_ads_client .get_service ("GoogleAdsService" )
8878
8979 # Row 1: Device Modifier
90- row1 = MagicMock (spec = ['ad_group_bid_modifier' , 'ad_group' , 'campaign' ])
91- row1 .campaign = MagicMock (spec = ['id' ])
80+ row1 = MockGoogleAdsRow () # Use MockGoogleAdsRow
9281 row1 .campaign .id = "campaign1"
93- row1 .ad_group = MagicMock (spec = ['id' ])
9482 row1 .ad_group .id = int (mock_ad_group_id )
9583
9684 modifier_device = MockAdGroupBidModifierModel (mock_google_ads_client .enums )
97- modifier_device .criterion_id = "100 "
85+ modifier_device .criterion_id = "test_crit_id_1 "
9886 modifier_device .bid_modifier = 1.5
9987 modifier_device .set_active_criterion_field ("device" )
10088 modifier_device .device .type_ = mock_google_ads_client .enums .DeviceEnum .MOBILE
10189 row1 .ad_group_bid_modifier = modifier_device
10290
10391 # Row 2: Hotel Check-in Day Modifier
104- row2 = MagicMock (spec = ['ad_group_bid_modifier' , 'ad_group' , 'campaign' ])
105- row2 .campaign = MagicMock (spec = ['id' ])
92+ row2 = MockGoogleAdsRow () # Use MockGoogleAdsRow
10693 row2 .campaign .id = "campaign2"
107- row2 .ad_group = MagicMock (spec = ['id' ])
10894 row2 .ad_group .id = int (mock_ad_group_id )
10995
11096 modifier_hotel_day = MockAdGroupBidModifierModel (mock_google_ads_client .enums )
111- modifier_hotel_day .criterion_id = "200 "
97+ modifier_hotel_day .criterion_id = "test_crit_id_2 "
11298 modifier_hotel_day .bid_modifier = 0.8
11399 modifier_hotel_day .set_active_criterion_field ("hotel_check_in_day" )
114100 modifier_hotel_day .hotel_check_in_day .day_of_week = mock_google_ads_client .enums .DayOfWeekEnum .MONDAY
@@ -130,24 +116,22 @@ def test_main_runs_successfully(mock_google_ads_client: MagicMock) -> None:
130116def test_main_runs_without_ad_group_id (mock_google_ads_client : MagicMock ) -> None :
131117 """Tests that the main function runs without an ad_group_id (fetches for all ad groups)."""
132118 mock_customer_id = "123"
133- mock_ad_group_id = None # Key difference for this test
119+ mock_ad_group_id = None
134120
135121 # --- Mock Enums (ensure they have .name attribute) ---
136122 mock_enums = mock_google_ads_client .enums
137123 mock_enums .DeviceEnum .TABLET = MagicMock (name = "DeviceEnum.TABLET" ); mock_enums .DeviceEnum .TABLET .name = "TABLET"
138- mock_enums .DeviceEnum .UNKNOWN = MagicMock (name = "DeviceEnum.UNKNOWN" ); mock_enums .DeviceEnum .UNKNOWN .name = "UNKNOWN_DEVICE_FOR_PRINT" # Default in class constructor matched
124+ mock_enums .DeviceEnum .UNKNOWN = MagicMock (name = "DeviceEnum.UNKNOWN" ); mock_enums .DeviceEnum .UNKNOWN .name = "UNKNOWN_DEVICE_NAME"
139125
140126 # --- Mock GoogleAdsService for search ---
141127 mock_googleads_service = mock_google_ads_client .get_service ("GoogleAdsService" )
142128
143- row1 = MagicMock (spec = ['ad_group_bid_modifier' , 'ad_group' , 'campaign' ])
144- row1 .campaign = MagicMock (spec = ['id' ])
129+ row1 = MockGoogleAdsRow () # Use MockGoogleAdsRow
145130 row1 .campaign .id = "campaign3"
146- row1 .ad_group = MagicMock (spec = ['id' ])
147131 row1 .ad_group .id = "987"
148132
149133 modifier1 = MockAdGroupBidModifierModel (mock_google_ads_client .enums )
150- modifier1 .criterion_id = "test_crit_id_3" # Using a more descriptive string for criterion ID
134+ modifier1 .criterion_id = "test_crit_id_3"
151135 modifier1 .bid_modifier = 1.2
152136 modifier1 .set_active_criterion_field ("device" )
153137 modifier1 .device .type_ = mock_google_ads_client .enums .DeviceEnum .TABLET
@@ -161,7 +145,7 @@ def test_main_runs_without_ad_group_id(mock_google_ads_client: MagicMock) -> Non
161145 main (
162146 mock_google_ads_client ,
163147 mock_customer_id ,
164- mock_ad_group_id , # None
148+ mock_ad_group_id ,
165149 )
166150 except Exception as e :
167151 pytest .fail (f"main function raised an exception: { e } " )
0 commit comments