Skip to content

Commit 66263ea

Browse files
Jules was unable to complete the task in time. Please review the work done so far and provide feedback for Jules to continue.
1 parent 4f350a8 commit 66263ea

12 files changed

+845
-0
lines changed

tests/examples/__init__.py

Whitespace-only changes.

tests/examples/basic_operations/__init__.py

Whitespace-only changes.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock, call # Ensure call is imported
3+
4+
from examples.basic_operations import add_ad_groups
5+
6+
class TestAddAdGroups(unittest.TestCase):
7+
8+
@patch("examples.basic_operations.add_ad_groups.argparse.ArgumentParser")
9+
@patch("examples.basic_operations.add_ad_groups.GoogleAdsClient.load_from_storage")
10+
def test_main(self, mock_load_from_storage, mock_argument_parser):
11+
# Mock the GoogleAdsClient
12+
mock_google_ads_client = MagicMock()
13+
mock_load_from_storage.return_value = mock_google_ads_client
14+
15+
# Mock the GoogleAdsService
16+
mock_ga_service = MagicMock()
17+
mock_google_ads_client.get_service.return_value = mock_ga_service
18+
19+
# Mock the AdGroupService
20+
mock_ad_group_service = MagicMock()
21+
# Ensure get_service is flexible enough to return different mocks based on input
22+
def get_service_side_effect(service_name, version=None): # Added version to match signature
23+
if service_name == "GoogleAdsService":
24+
return mock_ga_service
25+
elif service_name == "AdGroupService":
26+
return mock_ad_group_service
27+
raise ValueError(f"Unexpected service: {service_name}")
28+
mock_google_ads_client.get_service.side_effect = get_service_side_effect
29+
30+
31+
# Mock command line arguments
32+
mock_args = MagicMock()
33+
mock_args.customer_id = "1234567890"
34+
mock_args.campaign_id = "9876543210"
35+
mock_argument_parser.return_value.parse_args.return_value = mock_args
36+
37+
# Mock the responses for service calls
38+
# For AdGroupService mutate
39+
mock_ad_group_operation_response = MagicMock()
40+
# Simulate that one ad group was created
41+
mock_ad_group_result = MagicMock()
42+
mock_ad_group_result.resource_name = "customers/1234567890/adGroups/AD_GROUP_ID_1"
43+
mock_ad_group_operation_response.results = [mock_ad_group_result]
44+
mock_ad_group_service.mutate_ad_groups.return_value = mock_ad_group_operation_response
45+
46+
# Call the main function of the example script
47+
with patch("builtins.print") as mock_print:
48+
add_ad_groups.main(mock_google_ads_client, mock_args.customer_id, mock_args.campaign_id)
49+
50+
# Assertions
51+
mock_load_from_storage.assert_called_once_with(version="v19")
52+
mock_google_ads_client.get_service.assert_any_call("AdGroupService")
53+
# Allow GoogleAdsService to be called or not, as it's used for campaign existence check which might be mocked differently or not reached in a minimal test
54+
# mock_google_ads_client.get_service.assert_any_call("GoogleAdsService")
55+
56+
57+
self.assertEqual(mock_ad_group_service.mutate_ad_groups.call_count, 1)
58+
# Check the first argument of the first call to mutate_ad_groups
59+
args, kwargs = mock_ad_group_service.mutate_ad_groups.call_args
60+
self.assertEqual(kwargs['customer_id'], "1234567890")
61+
operations = kwargs['operations']
62+
self.assertEqual(len(operations), 2) # Expecting two ad group operations
63+
64+
# Example of checking one operation (can be more detailed)
65+
self.assertEqual(operations[0].create.name, f"Earth to Mars Cruises #{(0 + 1)}")
66+
self.assertEqual(operations[0].create.status, mock_google_ads_client.enums.AdGroupStatusEnum.PAUSED)
67+
self.assertEqual(operations[0].create.campaign, f"customers/1234567890/campaigns/9876543210")
68+
69+
70+
# Verify print output
71+
expected_print_calls = [
72+
call(f"Created ad group customers/1234567890/adGroups/AD_GROUP_ID_1.")
73+
]
74+
mock_print.assert_has_calls(expected_print_calls, any_order=False)
75+
76+
if __name__ == "__main__":
77+
unittest.main()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock, call
3+
4+
from examples.basic_operations import add_campaigns
5+
6+
class TestAddCampaigns(unittest.TestCase):
7+
8+
@patch("examples.basic_operations.add_campaigns.argparse.ArgumentParser")
9+
@patch("examples.basic_operations.add_campaigns.GoogleAdsClient.load_from_storage")
10+
def test_main(self, mock_load_from_storage, mock_argument_parser):
11+
# Mock the GoogleAdsClient
12+
mock_google_ads_client = MagicMock()
13+
mock_load_from_storage.return_value = mock_google_ads_client
14+
15+
# Mock the CampaignService
16+
mock_campaign_service = MagicMock()
17+
mock_google_ads_client.get_service.return_value = mock_campaign_service
18+
19+
# Mock command line arguments
20+
mock_args = MagicMock()
21+
mock_args.customer_id = "1234567890"
22+
mock_argument_parser.return_value.parse_args.return_value = mock_args
23+
24+
# Mock the responses for service calls
25+
mock_campaign_operation_response = MagicMock()
26+
# Simulate that one campaign was created
27+
mock_campaign_result = MagicMock()
28+
mock_campaign_result.resource_name = "customers/1234567890/campaigns/CAMPAIGN_ID_1"
29+
mock_campaign_operation_response.results = [mock_campaign_result]
30+
mock_campaign_service.mutate_campaigns.return_value = mock_campaign_operation_response
31+
32+
# Call the main function of the example script
33+
with patch("builtins.print") as mock_print:
34+
add_campaigns.main(mock_google_ads_client, mock_args.customer_id)
35+
36+
# Assertions
37+
mock_load_from_storage.assert_called_once_with(version="v19")
38+
mock_google_ads_client.get_service.assert_called_once_with("CampaignService")
39+
40+
self.assertEqual(mock_campaign_service.mutate_campaigns.call_count, 1)
41+
args, kwargs = mock_campaign_service.mutate_campaigns.call_args
42+
self.assertEqual(kwargs['customer_id'], "1234567890")
43+
operations = kwargs['operations']
44+
# The example creates 1 campaign, but the script has a loop for _NUMBER_OF_CAMPAIGNS (default 1)
45+
# For simplicity here, assuming _NUMBER_OF_CAMPAIGNS = 1 or that the test setup matches one operation.
46+
# If _NUMBER_OF_CAMPAIGNS was different, this would need adjustment or the constant mocked.
47+
self.assertEqual(len(operations), 1)
48+
49+
# Check properties of the created campaign operation
50+
campaign_op = operations[0].create
51+
self.assertTrue(campaign_op.name.startswith("Interplanetary Cruise #"))
52+
self.assertEqual(campaign_op.advertising_channel_type, mock_google_ads_client.enums.AdvertisingChannelTypeEnum.SEARCH)
53+
self.assertEqual(campaign_op.status, mock_google_ads_client.enums.CampaignStatusEnum.PAUSED)
54+
self.assertEqual(campaign_op.manual_cpc.enhanced_cpc_enabled, True)
55+
self.assertEqual(campaign_op.campaign_budget, mock_campaign_service.client.get_type("CampaignBudgetOperation").create.name) # This needs careful mocking if budget is created separately
56+
self.assertEqual(campaign_op.network_settings.target_google_search, True)
57+
58+
59+
# Verify print output
60+
# Assuming one campaign result as mocked
61+
expected_print_calls = [
62+
call(f"Created campaign customers/1234567890/campaigns/CAMPAIGN_ID_1.")
63+
]
64+
mock_print.assert_has_calls(expected_print_calls, any_order=False)
65+
66+
if __name__ == "__main__":
67+
unittest.main()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock, call
3+
4+
from examples.basic_operations import get_campaigns
5+
6+
class TestGetCampaigns(unittest.TestCase):
7+
8+
@patch("examples.basic_operations.get_campaigns.argparse.ArgumentParser")
9+
@patch("examples.basic_operations.get_campaigns.GoogleAdsClient.load_from_storage")
10+
def test_main(self, mock_load_from_storage, mock_argument_parser):
11+
# Mock the GoogleAdsClient
12+
mock_google_ads_client = MagicMock()
13+
mock_load_from_storage.return_value = mock_google_ads_client
14+
15+
# Mock the GoogleAdsService
16+
mock_ga_service = MagicMock()
17+
mock_google_ads_client.get_service.return_value = mock_ga_service
18+
19+
# Mock command line arguments
20+
mock_args = MagicMock()
21+
mock_args.customer_id = "1234567890"
22+
mock_argument_parser.return_value.parse_args.return_value = mock_args
23+
24+
# Mock the response from search_stream
25+
mock_row1 = MagicMock()
26+
mock_row1.campaign.id = "111"
27+
mock_row1.campaign.name = "Test Campaign 1"
28+
29+
mock_row2 = MagicMock()
30+
mock_row2.campaign.id = "222"
31+
mock_row2.campaign.name = "Test Campaign 2"
32+
33+
mock_batch1 = MagicMock()
34+
mock_batch1.results = [mock_row1, mock_row2]
35+
36+
mock_stream_response = [mock_batch1]
37+
mock_ga_service.search_stream.return_value = mock_stream_response
38+
39+
# Call the main function of the example script
40+
with patch("builtins.print") as mock_print:
41+
get_campaigns.main(mock_google_ads_client, mock_args.customer_id)
42+
43+
# Assertions
44+
mock_load_from_storage.assert_called_once_with(version="v19")
45+
mock_google_ads_client.get_service.assert_called_once_with("GoogleAdsService")
46+
47+
expected_query = """
48+
SELECT
49+
campaign.id,
50+
campaign.name
51+
FROM campaign
52+
ORDER BY campaign.id"""
53+
mock_ga_service.search_stream.assert_called_once_with(
54+
customer_id=mock_args.customer_id, query=expected_query
55+
)
56+
57+
# Verify print output
58+
expected_print_calls = [
59+
call("Campaign with ID 111 and name "Test Campaign 1" was found."),
60+
call("Campaign with ID 222 and name "Test Campaign 2" was found.")
61+
]
62+
mock_print.assert_has_calls(expected_print_calls, any_order=False)
63+
64+
if __name__ == "__main__":
65+
unittest.main()
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import unittest
2+
from unittest.mock import patch, MagicMock, call
3+
4+
from examples.basic_operations import get_responsive_search_ads
5+
6+
class TestGetResponsiveSearchAds(unittest.TestCase):
7+
8+
@patch("examples.basic_operations.get_responsive_search_ads.argparse.ArgumentParser")
9+
@patch("examples.basic_operations.get_responsive_search_ads.GoogleAdsClient.load_from_storage")
10+
def test_main(self, mock_load_from_storage, mock_argument_parser):
11+
# Mock the GoogleAdsClient
12+
mock_google_ads_client = MagicMock()
13+
mock_load_from_storage.return_value = mock_google_ads_client
14+
15+
# Mock the GoogleAdsService
16+
mock_ga_service = MagicMock()
17+
mock_google_ads_client.get_service.return_value = mock_ga_service
18+
19+
# Mock command line arguments
20+
mock_args = MagicMock()
21+
mock_args.customer_id = "1234567890"
22+
mock_args.ad_group_id = "ADGROUPID" # Optional, so test with and without
23+
mock_argument_parser.return_value.parse_args.return_value = mock_args
24+
25+
# Mock the response from search_stream
26+
mock_row1_ad = MagicMock()
27+
mock_row1_ad.resource_name = "customers/123/ads/RSA1"
28+
# Mock headlines
29+
mock_headline1 = MagicMock()
30+
mock_headline1.text = "Headline 1 RSA1"
31+
mock_headline1.asset_performance_label = mock_google_ads_client.enums.AssetPerformanceLabelEnum.PENDING
32+
mock_headline1.policy_summary.review_status = mock_google_ads_client.enums.PolicyReviewStatusEnum.REVIEWED
33+
mock_headline1.policy_summary.approval_status = mock_google_ads_client.enums.PolicyApprovalStatusEnum.APPROVED
34+
# Mock descriptions
35+
mock_desc1 = MagicMock()
36+
mock_desc1.text = "Description 1 RSA1"
37+
mock_desc1.asset_performance_label = mock_google_ads_client.enums.AssetPerformanceLabelEnum.LEARNING
38+
39+
mock_row1_ad.responsive_search_ad.headlines = [mock_headline1]
40+
mock_row1_ad.responsive_search_ad.descriptions = [mock_desc1]
41+
42+
43+
mock_row1 = MagicMock()
44+
mock_row1.ad_group_ad.ad = mock_row1_ad
45+
46+
mock_batch1 = MagicMock()
47+
mock_batch1.results = [mock_row1]
48+
49+
mock_stream_response = [mock_batch1]
50+
mock_ga_service.search_stream.return_value = mock_stream_response
51+
52+
# Call the main function of the example script
53+
with patch("builtins.print") as mock_print:
54+
# Test with ad_group_id
55+
get_responsive_search_ads.main(mock_google_ads_client, mock_args.customer_id, mock_args.ad_group_id)
56+
57+
# Test without ad_group_id (reset mock_args and mock_ga_service calls for a clean second run)
58+
mock_args.ad_group_id = None
59+
mock_ga_service.reset_mock() # Reset call counts etc.
60+
mock_ga_service.search_stream.return_value = mock_stream_response # Re-assign return value
61+
get_responsive_search_ads.main(mock_google_ads_client, mock_args.customer_id, mock_args.ad_group_id)
62+
63+
64+
# Assertions
65+
self.assertEqual(mock_load_from_storage.call_count, 2) # Called twice
66+
mock_load_from_storage.assert_called_with(version="v19") # Check one of the calls
67+
68+
self.assertEqual(mock_google_ads_client.get_service.call_count, 2)
69+
mock_google_ads_client.get_service.assert_called_with("GoogleAdsService")
70+
71+
# Check query for call WITH ad_group_id
72+
args_with, kwargs_with = mock_ga_service.search_stream.call_args_list[0]
73+
self.assertEqual(kwargs_with['customer_id'], "1234567890")
74+
self.assertIn("AND ad_group.id = 'ADGROUPID'", kwargs_with['query'])
75+
76+
# Check query for call WITHOUT ad_group_id
77+
args_without, kwargs_without = mock_ga_service.search_stream.call_args_list[1]
78+
self.assertEqual(kwargs_without['customer_id'], "1234567890")
79+
self.assertNotIn("AND ad_group.id", kwargs_without['query'])
80+
81+
# Verify print output (simplified for one call, can be expanded)
82+
# This will check the print calls from the first main() call (with ad_group_id)
83+
expected_print_calls = [
84+
call("Responsive search ad with resource name "
85+
""customers/123/ads/RSA1" was found."),
86+
call(" Headlines:"),
87+
call(" Headline text: Headline 1 RSA1"),
88+
call(" Performance: PENDING"),
89+
call(" Review status: REVIEWED"),
90+
call(" Approval status: APPROVED"),
91+
call(" Descriptions:"),
92+
call(" Description text: Description 1 RSA1"),
93+
call(" Performance: LEARNING"),
94+
]
95+
# mock_print.assert_has_calls(expected_print_calls, any_order=False)
96+
# Due to two calls to main, the above assert_has_calls will be tricky without more complex print mocking.
97+
# We can check if a specific print happened:
98+
mock_print.assert_any_call("Responsive search ad with resource name "
99+
""customers/123/ads/RSA1" was found.")
100+
101+
102+
if __name__ == "__main__":
103+
unittest.main()

0 commit comments

Comments
 (0)