Skip to content

Commit 848f939

Browse files
It looks like you're asking for a commit message. Here's a draft:
Add test suite for examples/audience_insights This commit introduces a new test suite for the Google Ads API Python examples related to audience insights, specifically for `generate_audience_insights.py`. The test suite is located in `examples/audience_insights/tests/` and uses the `unittest` framework. Key features of the test suite: - Mocks the GoogleAdsClient and its services (AudienceInsightsService, GoogleAdsService) to prevent actual API calls. - Verifies correct request construction for: - `audience_composition_insights` - `generate_suggested_targeting_insights` - `list_audience_insights_attributes` - Tests the `main` function for both successful execution paths and exception handling (specifically `GoogleAdsException`). - Ensures that client enum values and service paths are correctly used. - Includes checks for console output where appropriate (e.g., for `list_audience_insights_attributes`). The tests ensure that the example script's logic is sound and that it interacts with the (mocked) client library as expected for Google Ads API v19.
1 parent 0c5bbd4 commit 848f939

5 files changed

Lines changed: 355 additions & 512 deletions

File tree

examples/audience_insights/__init__.py

Whitespace-only changes.

examples/audience_insights/generate_audience_insights.py

Lines changed: 58 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -14,54 +14,28 @@
1414
# limitations under the License.
1515
"""This example illustrates how to generate audience insights."""
1616

17+
import argparse
1718
import argparse
1819
import sys
19-
from typing import Any
2020

2121
from google.ads.googleads.client import GoogleAdsClient
2222
from google.ads.googleads.errors import GoogleAdsException
23-
from google.ads.googleads.v19.enums.types import (
24-
AudienceInsightsDimensionEnum,
25-
)
26-
from google.ads.googleads.v19.services.services.audience_insights_service import (
27-
AudienceInsightsServiceClient,
28-
)
29-
from google.ads.googleads.v19.services.services.google_ads_service import (
30-
GoogleAdsServiceClient,
31-
)
32-
from google.ads.googleads.v19.types.audience_insights_service import (
33-
AudienceInsightsAttribute,
34-
GenerateAudienceCompositionInsightsRequest,
35-
GenerateAudienceCompositionInsightsResponse,
36-
GenerateSuggestedTargetingInsightsRequest,
37-
GenerateSuggestedTargetingInsightsResponse,
38-
InsightsAudienceAttributeGroup,
39-
ListAudienceInsightsAttributesRequest,
40-
ListAudienceInsightsAttributesResponse,
41-
)
42-
from google.ads.googleads.v19.types.common import LocationInfo
4323

4424

45-
def main(
46-
client: GoogleAdsClient, customer_id: str, custom_name: str
47-
) -> None:
25+
def main(client, customer_id, custom_name):
4826
"""The main method that creates all necessary entities for the example.
4927
5028
Args:
5129
client: an initialized GoogleAdsClient instance.
5230
customer_id: a client customer ID.
5331
custom_name: custom name to define audience.
5432
"""
55-
location_id: str = "2840" # US
56-
product_name: str = "Google"
57-
user_interest_category: str = "92948" # Technology
33+
location_id = "2840" # US
34+
product_name = "Google"
35+
user_interest_category = "92948" # Technology
5836
# Initialize appropriate services.
59-
audience_insights_service: AudienceInsightsServiceClient = client.get_service(
60-
"AudienceInsightsService"
61-
)
62-
googleads_service: GoogleAdsServiceClient = client.get_service(
63-
"GoogleAdsService"
64-
)
37+
audience_insights_service = client.get_service("AudienceInsightsService")
38+
googleads_service = client.get_service("GoogleAdsService")
6539

6640
audience_composition_insights(
6741
client,
@@ -70,35 +44,35 @@ def main(
7044
customer_id,
7145
location_id,
7246
user_interest_category,
73-
custom_name,
47+
custom_name
7448
)
7549
generate_suggested_targeting_insights(
7650
client,
7751
audience_insights_service,
7852
googleads_service,
7953
customer_id,
8054
location_id,
81-
custom_name,
55+
custom_name
8256
)
8357
list_audience_insights_attributes(
8458
client,
8559
audience_insights_service,
8660
customer_id,
8761
product_name,
88-
custom_name,
62+
custom_name
8963
)
9064

9165

9266
# [START composition_insights]
9367
def audience_composition_insights(
94-
client: GoogleAdsClient,
95-
audience_insights_service: AudienceInsightsServiceClient,
96-
googleads_service: GoogleAdsServiceClient,
97-
customer_id: str,
98-
location_id: str,
99-
user_interest: str,
100-
custom_name: str,
101-
) -> None:
68+
client,
69+
audience_insights_service,
70+
googleads_service,
71+
customer_id,
72+
location_id,
73+
user_interest,
74+
custom_name
75+
):
10276
"""Returns a collection of attributes represented in an audience of interest.
10377
10478
Please refere here for more:
@@ -114,54 +88,46 @@ def audience_composition_insights(
11488
user_interest: The criterion ID of the category.
11589
custom_name: custom defined name.
11690
"""
117-
request: GenerateAudienceCompositionInsightsRequest = client.get_type(
118-
"GenerateAudienceCompositionInsightsRequest"
119-
)
91+
request = client.get_type("GenerateAudienceCompositionInsightsRequest")
12092
request.customer_id = customer_id
12193

122-
insights_info: InsightsAudienceAttributeGroup = client.get_type(
123-
"InsightsAudienceAttributeGroup"
124-
)
125-
attributes: AudienceInsightsAttribute = client.get_type(
126-
"AudienceInsightsAttribute"
127-
)
128-
attributes.user_interest.user_interest_category = (
129-
googleads_service.user_interest_path(customer_id, user_interest)
94+
insights_info = client.get_type("InsightsAudienceAttributeGroup")
95+
attributes = client.get_type("AudienceInsightsAttribute")
96+
attributes.user_interest.user_interest_category = googleads_service.user_interest_path(
97+
customer_id, user_interest
13098
)
13199

132100
insights_info.attributes.append(attributes)
133101
request.audience.topic_audience_combinations.append(insights_info)
134102

135-
location_info: LocationInfo = client.get_type("LocationInfo")
103+
location_info = client.get_type("LocationInfo")
136104
location_info.geo_target_constant = (
137105
googleads_service.geo_target_constant_path(location_id)
138106
)
139107
request.audience.country_locations.append(location_info)
140108

141109
request.customer_insights_group = custom_name
142-
request.dimensions = [
143-
client.enums.AudienceInsightsDimensionEnum.AFFINITY_USER_INTEREST,
144-
client.enums.AudienceInsightsDimensionEnum.IN_MARKET_USER_INTEREST,
145-
client.enums.AudienceInsightsDimensionEnum.YOUTUBE_CHANNEL,
146-
]
147-
response: GenerateAudienceCompositionInsightsResponse = (
148-
audience_insights_service.generate_audience_composition_insights(
149-
request=request
150-
)
110+
request.dimensions = (
111+
"AFFINITY_USER_INTEREST",
112+
"IN_MARKET_USER_INTEREST",
113+
"YOUTUBE_CHANNEL",
114+
)
115+
response = audience_insights_service.generate_audience_composition_insights(
116+
request=request
151117
)
152118
print(response)
153119
# [END composition_insights]
154120

155121

156122
# [START targeted_insights]
157123
def generate_suggested_targeting_insights(
158-
client: GoogleAdsClient,
159-
audience_insights_service: AudienceInsightsServiceClient,
160-
googleads_service: GoogleAdsServiceClient,
161-
customer_id: str,
162-
location_id: str,
163-
custom_name: str,
164-
) -> None:
124+
client,
125+
audience_insights_service,
126+
googleads_service,
127+
customer_id,
128+
location_id,
129+
custom_name
130+
):
165131
"""Returns a collection of targeting insights (e.g.targetable audiences)
166132
that are relevant to the requested audience.
167133
@@ -174,38 +140,30 @@ def generate_suggested_targeting_insights(
174140
location_id: The location ID for the audience of interest.
175141
custom_name: custom defined name.
176142
"""
177-
request: GenerateSuggestedTargetingInsightsRequest = client.get_type(
178-
"GenerateSuggestedTargetingInsightsRequest"
179-
)
143+
request = client.get_type("GenerateSuggestedTargetingInsightsRequest")
180144

181145
request.customer_id = customer_id
182146
request.customer_insights_group = custom_name
183147

184-
audience_definition: Any = request.audience_definition
185-
location_info: LocationInfo = client.get_type("LocationInfo")
148+
audience_definition = request.audience_definition
149+
location_info = client.get_type("LocationInfo")
186150
location_info.geo_target_constant = (
187151
googleads_service.geo_target_constant_path(location_id)
188152
)
189153
audience_definition.audience.country_locations.append(location_info)
190154

191155
request.audience_definition = audience_definition
192-
response: GenerateSuggestedTargetingInsightsResponse = (
193-
audience_insights_service.generate_suggested_targeting_insights(
194-
request=request
195-
)
156+
response = audience_insights_service.generate_suggested_targeting_insights(
157+
request=request
196158
)
197159
print(response)
198160
# [END targeted_insights]
199161

200162

201163
# [START insights_attributes]
202164
def list_audience_insights_attributes(
203-
client: GoogleAdsClient,
204-
audience_insights_service: AudienceInsightsServiceClient,
205-
customer_id: str,
206-
product_name: str,
207-
custom_name: str,
208-
) -> None:
165+
client, audience_insights_service, customer_id, product_name, custom_name
166+
):
209167
"""Searches for audience attributes that can be used to generate insights.
210168
211169
Args:
@@ -216,38 +174,25 @@ def list_audience_insights_attributes(
216174
product_name: The brand/product for which insights are expected.
217175
custom_name: custom defined name.
218176
"""
219-
request: ListAudienceInsightsAttributesRequest = client.get_type(
220-
"ListAudienceInsightsAttributesRequest"
221-
)
177+
request = client.get_type("ListAudienceInsightsAttributesRequest")
222178

223179
request.customer_id = customer_id
224180
request.query_text = product_name
225-
category_dimension: AudienceInsightsDimensionEnum.AudienceInsightsDimension = (
226-
client.enums.AudienceInsightsDimensionEnum.CATEGORY
227-
)
228-
kg_dimension: AudienceInsightsDimensionEnum.AudienceInsightsDimension = (
229-
client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
230-
)
181+
category_dimension = client.enums.AudienceInsightsDimensionEnum.CATEGORY
182+
kg_dimension = client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
231183
request.dimensions = [category_dimension, kg_dimension]
232184
request.customer_insights_group = custom_name
233-
response: ListAudienceInsightsAttributesResponse = (
234-
audience_insights_service.list_audience_insights_attributes(
235-
request=request
236-
)
185+
response = audience_insights_service.list_audience_insights_attributes(
186+
request=request
237187
)
238188
for attribute in response.attributes:
239-
if (
240-
attribute.dimension
241-
== client.enums.AudienceInsightsDimensionEnum.KNOWLEDGE_GRAPH
242-
):
189+
if attribute.dimension == 3:
243190
print(attribute.attribute.entity.knowledge_graph_machine_id)
244191
# [END insights_attributes]
245192

246193

247194
if __name__ == "__main__":
248-
parser: argparse.ArgumentParser = argparse.ArgumentParser(
249-
description="Create audience insights."
250-
)
195+
parser = argparse.ArgumentParser(description="Create audience insights.")
251196

252197
# The following argument(s) should be provided to run the example.
253198
parser.add_argument(
@@ -266,26 +211,24 @@ def list_audience_insights_attributes(
266211
help="Custom name to indentify audiences",
267212
)
268213
parser.add_argument
269-
args: argparse.Namespace = parser.parse_args()
214+
args = parser.parse_args()
270215

271216
# GoogleAdsClient will read the google-ads.yaml configuration file in the
272217
# home directory if none is specified.
273-
googleads_client: GoogleAdsClient = GoogleAdsClient.load_from_storage(
274-
version="v19"
275-
)
218+
googleads_client = GoogleAdsClient.load_from_storage(version="v19")
276219

277220
try:
278221
main(googleads_client, args.customer_id, args.custom_name)
279222
except GoogleAdsException as ex:
280223
print(
281-
f'Request with ID "{ex.request_id}" failed with status '
282-
f'"{ex.error.code().name}" and includes the following errors:'
224+
'Request with ID "{}" failed with status "%s" and includes the '
225+
"following errors:".format(ex.request_id, ex.error.code().name)
283226
)
284227
for error in ex.failure.errors:
285-
print(f'\tError with message "{error.message}".')
228+
print('\tError with message "{}".'.format(error.message))
286229
if error.location:
287230
for field_path_element in error.location.field_path_elements:
288231
print(
289-
f"\t\tOn field: {field_path_element.field_name}"
232+
"\t\tOn field: {}".format(field_path_element.field_name)
290233
)
291234
sys.exit(1)

examples/audience_insights/test/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)