Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add analytics models and tests #117

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
60a0844
Analytics base model outline and fields (#34)
rushabhvaria Dec 20, 2022
5637518
Ad Account `get_analytics` (#40)
rushabhvaria Dec 24, 2022
2cbfdc8
implement `get_targeting_analytics` for AdAccount model (#43)
rushabhvaria Jan 23, 2023
e19375e
Update with last main changes (#61)
dfana01 Jan 26, 2023
06ef79e
feat(analytics): add get_targeting_analytics to ad group (#66)
dfana01 Jan 31, 2023
d9c0967
Add get targeting analytics for ads (#65)
dfana01 Jan 31, 2023
b2afb5b
Add Ad group analytics (#64)
dfana01 Feb 1, 2023
2a64f1f
Add get ads analytics (#62)
dfana01 Feb 1, 2023
b7e7eb7
feat: add analytics and targeting (#72)
dfana01 Feb 1, 2023
93aef8e
Add get pin analytic (#73)
dfana01 Feb 3, 2023
e6f78af
fix conflicts
dfana01 Feb 8, 2023
060890f
fix conflicts
dfana01 Feb 8, 2023
12a9f63
Point to doc page on devsite (#58)
thucngyyen Jan 24, 2023
48b9190
Ad Account `get_analytics` (#40)
rushabhvaria Dec 24, 2022
ca35a5d
fix conflicts
dfana01 Feb 8, 2023
79c801c
Add get pin analytic (#73)
dfana01 Feb 3, 2023
ec3b96a
fix conflics
dfana01 Feb 8, 2023
b9eb788
fix conflicts
dfana01 Feb 8, 2023
e987f8e
fix conflicts
thucngyyen Jan 31, 2023
7ff4844
fix conflicts
dfana01 Feb 8, 2023
dc7b308
Merge branch 'main' of github.com:pinterest/pinterest-python-sdk into…
gilderlane Aug 16, 2023
6efe21d
Integration tests for ad_groups analytics
gilderlane Oct 2, 2023
ffb70b4
Integrationn tests for ads analytics
gilderlane Oct 2, 2023
e2c051b
Integration tests for campaigns analytics
gilderlane Oct 2, 2023
cb9bfdb
Integration tests for pins analytics
gilderlane Oct 2, 2023
e2061cc
Update integration tests for conversion events to test failure by ass…
gilderlane Oct 2, 2023
9bef17e
Update board and pin models with new properties
gilderlane Oct 2, 2023
bdb4cc6
Fix valition of responses
gilderlane Oct 2, 2023
57f9b23
Avoid deletion of defatult test pin
gilderlane Oct 2, 2023
de41ef4
Fix creative type for deafulttest pin
gilderlane Oct 2, 2023
0895036
Update requirements.txt and setup.py to match last veersion of Pinter…
gilderlane Oct 2, 2023
aa682d4
Update config with new env variables
gilderlane Oct 2, 2023
adccaa0
Update clean organic data
gilderlane Oct 2, 2023
cdc37ae
Update integration tests for ad accounts analytics
gilderlane Oct 2, 2023
e64cdf4
Fix lint problems
gilderlane Oct 3, 2023
8028bc8
Update unit test
gilderlane Oct 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ignore=CVS
# ignore-list. The regex matches against paths and can be in Posix or Windows
# format. Because '\' represents the directory delimiter on Windows systems, it
# can't be used as an escape character.
ignore-paths=generated,.venv,venv,docs,samples,package_test,integration_tests
ignore-paths=generated,.venv,venv,docs,samples,package_test,integration_tests,pinterest/utils/validations.py

# Files or directories matching the regular expression patterns are skipped.
# The regex matches against base names, not paths. The default value ignores
Expand Down Expand Up @@ -473,7 +473,7 @@ max-returns=6
max-statements=50

# Minimum number of public methods for a class (see R0903).
min-public-methods=2
min-public-methods=1


[STRING]
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ campaign.set_lifetime_budget(

* Documentation is hosted on [Developer Site](https://developers.pinterest.com/docs/sdk/).


## Exceptions

See `pinterest.utils.sdk_exceptions` for a list of exceptions which may be thrown by the SDK.
Expand Down
63 changes: 61 additions & 2 deletions integration_tests/ads/test_ad_accounts.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
"""
Test Ad Account Model
"""

from datetime import date
from datetime import timedelta
from parameterized import parameterized
from unittest.mock import patch

from pinterest.ads.ad_accounts import AdAccount
from pinterest.ads.campaigns import Campaign
from pinterest.ads.audiences import Audience

from integration_tests.base_test import BaseTestCase
from integration_tests.config import OWNER_USER_ID, DEFAULT_AD_ACCOUNT_ID
from integration_tests.config import OWNER_USER_ID
from integration_tests.config import DEFAULT_AD_ACCOUNT_ID


class TestAdAccount(BaseTestCase):
Expand Down Expand Up @@ -136,3 +139,59 @@ def test_list_customer_list_success(self):
get_all_customer_list_ids.add(getattr(customer_list, "_id"))

assert new_customer_list_ids == get_all_customer_list_ids


class TestGetAnalytics(BaseTestCase):
"""
Test getting Ad accounts analytics
"""
DAYS_BACK = 2
FURTHEST_BACK_HOUR = 7 # Futhest allowed days back for granularity HOUR
MAX_RANGE_DAYS = 3 # Max time range in days for granularity HOUR
FURTHEST_BACK_NOT_HOUR = 90 # Futhest allowed days back for any granularity but HOUR

@parameterized.expand(
[
("granularity_total","TOTAL"),
("granularity_day", "DAY"),
("granularity_hour", "HOUR"),
("granularity_week", "WEEK"),
("granularity_month", "MONTH"),
]
)
def test_get_ad_analytics_success(self, name, granularity):
analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(self.DAYS_BACK),
'end_date': date.today(),
'columns': ["ADVERTISER_ID","PIN_PROMOTION_ID","SPEND_IN_DOLLAR"],
'granularity': granularity,
}
ad_account = AdAccount(
ad_account_id=self.ad_account_utils.get_default_ad_account_id(),
client=self.test_client
)
ad_account_analytics = ad_account.get_analytics(**analytics_info_dict)
self.assertIsNotNone(ad_account_analytics)
self.assertIsNotNone(ad_account_analytics.raw_response)


class TestGetTargetingAnalytics(BaseTestCase):

def test_get_ad_targeting_analytics_success(self):
analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(2),
'end_date': date.today(),
'targeting_types':["GENDER"],
'columns': ["ADVERTISER_ID","PIN_PROMOTION_ID","SPEND_IN_DOLLAR"],
'granularity': 'DAY',
}
ad_account = AdAccount(
ad_account_id=self.ad_account_utils.get_default_ad_account_id(),
client=self.test_client
)
ad_analytics = ad_account.get_targeting_analytics(**analytics_info_dict)
self.assertIsNotNone(ad_analytics)
self.assertIsNotNone(ad_analytics.raw_response)
self.assertIsNotNone(ad_analytics.raw_response.get('data'))
147 changes: 143 additions & 4 deletions integration_tests/ads/test_ad_groups.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
'''
Test AdGroup Model
'''
from datetime import date
from datetime import timedelta
from parameterized import parameterized

from openapi_generated.pinterest_client.exceptions import ApiException
from openapi_generated.pinterest_client.model.targeting_spec import TargetingSpec

from integration_tests.base_test import BaseTestCase
from integration_tests.config import DEFAULT_AD_ACCOUNT_ID
from integration_tests.config import DEFAULT_AD_ACCOUNT_ID, DEFAULT_AD_GROUP_ID

from pinterest.ads.ad_groups import AdGroup

Expand Down Expand Up @@ -63,9 +69,7 @@ def test_update_success(self):
)

new_name = "SDK_AD_GROUP_NEW_NAME"
new_spec = {
"GENDER": ["male"]
}
new_spec = TargetingSpec(gender=["male"])

ad_group.update_fields(
name=new_name,
Expand Down Expand Up @@ -221,3 +225,138 @@ def test_disable_auto_targeting(self):
ad_group_id=getattr(ad_group_0, "_id")
)
self.assertFalse(getattr(ad_group_1, "_auto_targeting_enabled"))


class TestGetAnalytics(BaseTestCase):
"""
Test getting Ad Group analytics
"""
DAYS_BACK = 2
FURTHEST_DAYS_BACK_HOUR = 7 # Futhest allowed days back for granularity HOUR
FURTHEST_DAYS_BACK_NOT_HOUR = 90 # Futhest allowed days back for any granularity but HOUR

@parameterized.expand(
[
("granularity_total","TOTAL"),
("granularity_day", "DAY"),
("granularity_hour", "HOUR"),
("granularity_week", "WEEK"),
("granularity_month", "MONTH"),
]
)
def test_get_ad_group_analytics_success(self, name, granularity):

analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(self.DAYS_BACK),
'end_date': date.today(),
'columns': ["ADVERTISER_ID","TOTAL_ENGAGEMENT","SPEND_IN_DOLLAR"],
'granularity': granularity,
}
ad_group = AdGroup(
ad_account_id=DEFAULT_AD_ACCOUNT_ID,
ad_group_id=DEFAULT_AD_GROUP_ID,
client=self.test_client,
)

ad_group_analytics = ad_group.get_analytics(**analytics_info_dict)
self.assertIsNotNone(ad_group_analytics)
self.assertIsNotNone(ad_group_analytics.raw_response)
analytics_response = ad_group_analytics.raw_response.get('value')
for dict_item in analytics_response:
for column in analytics_info_dict.get('columns'):
self.assertIn(column, dict_item)
if granularity != 'TOTAL':
self.assertIn('DATE', dict_item)

@parameterized.expand(
[
("granularity_total","TOTAL", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_day", "DAY", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_hour", "HOUR", FURTHEST_DAYS_BACK_HOUR + 1),
("granularity_week", "WEEK", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_month", "MONTH", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
]
)
def test_get_analytics_fail(self, name, granularity, days_back):
analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(days_back),
'end_date': date.today(),
'columns': ["ADVERTISER_ID","PIN_PROMOTION_ID","SPEND_IN_DOLLAR"],
'granularity': granularity,
}
ad_group = AdGroup(
ad_account_id=DEFAULT_AD_ACCOUNT_ID,
ad_group_id=DEFAULT_AD_GROUP_ID,
client=self.test_client,
)
with self.assertRaises(ApiException):
ad_group.get_analytics(**analytics_info_dict)

class TestGetTargetingAnalytics(BaseTestCase):
"""
Test getting targeting analytics for Ad Group
"""
DAYS_BACK = 2
FURTHEST_DAYS_BACK_HOUR = 7 # Futhest allowed days back for granularity HOUR
FURTHEST_DAYS_BACK_NOT_HOUR = 90 # Futhest allowed days back for any granularity but HOUR

@parameterized.expand(
[
("granularity_total","TOTAL"),
("granularity_day", "DAY"),
("granularity_week", "WEEK"),
("granularity_month", "MONTH"),
]
)
def test_get_ad_group_targeting_analytics_success(self, name, granularity):
analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(self.DAYS_BACK),
'end_date': date.today(),
'targeting_types':["GENDER"],
'columns': ["SPEND_IN_MICRO_DOLLAR","SPEND_IN_DOLLAR", "TOTAL_ENGAGEMENT"],
'granularity': granularity,
}
ad_group = AdGroup(
ad_account_id=DEFAULT_AD_ACCOUNT_ID,
ad_group_id=DEFAULT_AD_GROUP_ID,
client=self.test_client,
)
ad_group_analytics = ad_group.get_targeting_analytics(**analytics_info_dict)
self.assertIsNotNone(ad_group_analytics)
self.assertIsNotNone(ad_group_analytics.raw_response)
analytics_response = ad_group_analytics.raw_response.get('data')
for dict_item in analytics_response:
self.assertIsNotNone(dict_item.get('metrics'))
for column in analytics_info_dict.get('columns'):
self.assertIn(column, dict_item.get('metrics'))
if granularity != 'TOTAL':
self.assertIn('DATE', dict_item.get('metrics'))

@parameterized.expand(
[
("granularity_total","TOTAL", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_day", "DAY", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_hour", "HOUR", FURTHEST_DAYS_BACK_HOUR + 1),
("granularity_week", "WEEK", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
("granularity_month", "MONTH", FURTHEST_DAYS_BACK_NOT_HOUR + 1),
]
)
def test_get_ad_group_targeting_analytics_success(self, name, granularity, days_back):
analytics_info_dict = {
'ad_account_id': DEFAULT_AD_ACCOUNT_ID,
'start_date': date.today() - timedelta(days_back),
'end_date': date.today(),
'targeting_types':["GENDER"],
'columns': ["SPEND_IN_MICRO_DOLLAR","SPEND_IN_DOLLAR", "TOTAL_ENGAGEMENT"],
'granularity': granularity,
}
ad_group = AdGroup(
ad_account_id=DEFAULT_AD_ACCOUNT_ID,
ad_group_id=DEFAULT_AD_GROUP_ID,
client=self.test_client,
)
with self.assertRaises(ApiException):
ad_group.get_targeting_analytics(**analytics_info_dict)
Loading
Loading