feat(google-ads): upgrade SDK to 2.0.0, add full unit + integration test suite#317
feat(google-ads): upgrade SDK to 2.0.0, add full unit + integration test suite#317Shubhank-Jonnada wants to merge 7 commits into
Conversation
…unit + integration coverage (#)
- Bump autohive-integrations-sdk to 2.0.0 in requirements.txt
- Update google_ads.py: fix ValidationError in retrieve_campaign_metrics,
align all action handlers with SDK 2.0.0 execute_action return contract
(IntegrationResult with .type / .result.data / .result.message)
- Replace single monolithic test file with 9 focused test modules:
test_google_ads_accounts_unit.py
test_google_ads_campaigns_unit.py
test_google_ads_ad_groups_unit.py
test_google_ads_ads_unit.py
test_google_ads_keywords_unit.py
test_google_ads_keyword_planner_unit.py
test_google_ads_search_terms_unit.py
test_google_ads_helpers_unit.py
test_google_ads_integration.py (live, skipped in CI)
- 149 unit tests, all passing
- Integration test fixture uses GOOGLE_ADS_ACCESS_TOKEN directly
(no refresh token needed), mirroring the google-sheets SDK v2 pattern
- Add run_live_readonly.py standalone script for quick manual smoke tests
- Remove legacy tests/context.py and tests/test_google_ads.py
Why we couldn't live-test all actionsWe attempted live integration tests against the real Google Ads API using a short-lived access token. The token authenticated successfully, but the developer token is currently approved for test accounts only ( What passed live:
What was blocked by the API (not code):
What covers the gap: How to run live tests once the developer token is approvedexport GOOGLE_ADS_ACCESS_TOKEN="ya29.a0..."
export ADWORDS_DEVELOPER_TOKEN="<token>"
export GOOGLE_ADS_LOGIN_CUSTOMER_ID="<mcc_id>"
export GOOGLE_ADS_CUSTOMER_ID="<client_id>"
pytest google-ads/tests/test_google_ads_integration.py -m integration -v |
🔍 Integration Validation ResultsCommit: Changed directories:
|
… 2.1.0 - Fix E402 imports in run_live_readonly.py (moved to top) - Fix E501 long lines in test_google_ads_ad_groups_unit.py and run_live_readonly.py - Remove unused patch import from test_google_ads_integration.py - Add nosec B105 to bandit false positives (PASS symbol, placeholder check) - Run ruff format across all test files - Bump config.json version 2.0.1 → 2.1.0 (minor: new actions added)
- Refactor _validate_auth_and_inputs -> _validate_auth (auth only) - Each handler now explicitly accesses inputs["login_customer_id"] and inputs["customer_id"] directly, making them visible to the code checker - Change inputs.get() to inputs[] for all truly required fields per config.json (campaign_name, budget_amount_micros, campaign_id, ad_group_name, ad_group_id, keywords, criterion_id, ad_id, headlines, descriptions, final_url, campaign_ids/ad_group_ids in retrieve_keyword_metrics, date_ranges in retrieve_ad_group/ad/search_terms) - Remove redundant manual validation guards that are now handled by SDK schema
… version to 3.0.0
|
Updated this PR with the final SDK2/auth cleanup pass. What changed:
Validation run locally:
|
TheRealAgentK
left a comment
There was a problem hiding this comment.
Self-approved to remove the block, needs 3rd party review and then e-2-e test runs.
Summary
google_ads.pyandrequirements.txtto useautohive-integrations-sdk~=2.0.0. Action handlers return the SDK2IntegrationResultshape withActionResult/ActionErroras appropriate.config.jsonuses platform OAuth. The integration now reads the platform OAuthcredentials.access_tokenfromcontext.authand builds the Google Ads SDK client from that access token.ADWORDS_DEVELOPER_TOKENremains server-side API configuration, not a user auth field.ADWORDS_CLIENT_ID/ADWORDS_CLIENT_SECRETare no longer required by the tests or source import path..envloading / required env var reads fromgoogle_ads.py, so tests and runtime failures happen at action execution time instead of module import.test_google_ads.pywith focused unit test modules covering every action in the integration.test_google_ads_integration.pynow uses the sharedenv_credentials+make_contextpattern, platform OAuth-shapedctx.auth, a token extraction recipe, and safe read-only command first.Test coverage
test_google_ads_accounts_unit.pyget_accessible_accountstest_google_ads_campaigns_unit.pyretrieve_campaign_metrics,create_campaign,update_campaign,remove_campaigntest_google_ads_ad_groups_unit.pyretrieve_ad_group_metrics,create_ad_group,update_ad_group,remove_ad_grouptest_google_ads_ads_unit.pyretrieve_ad_metrics,create_responsive_search_ad,update_ad,remove_adtest_google_ads_keywords_unit.pyretrieve_keyword_metrics,add_keywords,update_keyword,remove_keywordtest_google_ads_keyword_planner_unit.pygenerate_keyword_ideas,generate_keyword_historical_metrics,generate_keyword_forecasttest_google_ads_search_terms_unit.pyretrieve_search_terms,get_active_ad_urlstest_google_ads_helpers_unit.pyadd_negative_keywords_to_campaign,add_negative_keywords_to_ad_grouptest_google_ads_integration.pydestructivemarkerLive test auth requirements
Required for read-only live tests:
GOOGLE_ADS_ACCESS_TOKEN— platform OAuth access tokenADWORDS_DEVELOPER_TOKEN— Google Ads API developer tokenGOOGLE_ADS_LOGIN_CUSTOMER_ID— manager/MCC account ID without dashesGOOGLE_ADS_CUSTOMER_ID— customer account ID without dashesOptional for destructive tests:
GOOGLE_ADS_TEST_CAMPAIGN_IDGOOGLE_ADS_TEST_AD_GROUP_IDSafe read-only command:
pytest google-ads/tests/test_google_ads_integration.py -m "integration and not destructive"Destructive command, only for safe test accounts:
pytest google-ads/tests/test_google_ads_integration.py -m "integration and destructive"Test plan
python -m pytest google-ads/tests -m unit -q— 149 passedpython -m pytest google-ads/tests/test_google_ads_integration.py -m "integration and not destructive" -q— 17 skipped without live credentials, 5 destructive deselectedpython -m pytest google-ads/ -q— 149 passedpython ../autohive-integrations-tooling/scripts/validate_integration.py google-ads— passed with one existing scope warning forhttps://www.googleapis.com/auth/adwordspython ../autohive-integrations-tooling/scripts/check_code.py google-ads— passed