def strategy_statuses(creative_statuses): '''Fixture with one strategy with all available statuses and another clean''' strategy_problematic = {'name': 'Strategy problematic', 'campaign': 'I\'m a fruit', 'budget_total': 0, 'budget_bid_CPM': Decimal('0.1')} strategy_clean = {'name': 'Strategy clean', 'campaign': 'I\'m a fruit', 'budget_total': 1000, 'budget_bid_CPM': Decimal('0.1')} setup = creative_statuses setup.setup_landing_pages() setup.setup_campaigns() setup.setup_strategies([strategy_problematic, strategy_clean]) ADVERTS = [ {'name': 'Ad audited', 'strategy': 'Strategy clean', 'creative': 'Image audited'}, {'name': 'Ad audited', 'strategy': 'Strategy problematic', 'creative': 'Image audited'}, {'name': 'Ad audit pending', 'strategy': 'Strategy problematic', 'creative': 'Image audit pending'}, {'name': 'Ad audit rejected', 'strategy': 'Strategy problematic', 'creative': 'Image audit rejected'}, {'name': 'Ad audit blocked', 'strategy': 'Strategy problematic', 'creative': 'Image audit blocked'}, {'name': 'Ad audit expired', 'strategy': 'Strategy problematic', 'creative': 'Image audit expired'} ] for advert in ADVERTS: advert.update({'url': 'http://www.google.com/'}) setup.setup_adverts([advert]) call_command('rebuild_index', interactive=False) return setup
def distribute_sum_randomly(n, total): """ Return a randomly chosen list of n numbers summing to total. Depends on total type values will be integers or Decimals. Examples: >>> distribute_sum_randomly(5, 100) >>> [5, 21, 57, 13, 4] >>> distribute_sum_randomly(3, Decimal('84.65')) >>> [Decimal('41.94'), Decimal('27.15'), Decimal('15.56')] """ if total == 0 or total == Decimal('0'): return [total for i in xrange(0, n)] dividers = [] for i in xrange(1, n): if isinstance(total, int): divider = random.randint(1, total) else: divider_decimal = random.random() * float(total) divider = Decimal('%f' % divider_decimal) dividers.append(divider) dividers.sort() return [a - b for a, b in zip(dividers + [total], [0] + dividers)]
def db_factory_four_strategies(bidding_app): strategies = [ {'name': 'Strategy 3', 'campaign': 'I\'m a fruit', 'budget_total': 8000, 'budget_bid_CPM': Decimal('0.1')}, {'name': 'Strategy 4', 'campaign': 'I\'m a fruit', 'budget_total': 4321, 'budget_bid_CPM': Decimal('0.1')} ] bidding_app.setup_strategies(strategies) return bidding_app
def total_spent(self): """ Sum of all account spendings (commission included). """ aggregation = self.campaign_set.aggregate( sum=Sum('budget_spent'), commission=Sum('budget_spent_commission')) return (aggregation['sum'] or Decimal(0)) + \ (aggregation['commission'] or Decimal(0)) + \ self.audit_fees
def get_randomized_metrics(self, budget, base_cpm): """ Generate basic metrics values within ranges provided in configuration :return: values for BASE_METRICS :rtype: dict """ conf = self.options commission_value = budget / (Decimal(1) + COMMISSION) inventory_cost = budget - commission_value data_cost_value = randint( *conf['DATA_COST_RANGE']) / Decimal(100) * inventory_cost imp_value = inventory_cost - data_cost_value cpm = randint(*conf['BID_CPM_RANGE']) / Decimal(100) * base_cpm imp = imp_value * 1000 / cpm ctr = randint(*conf['CTR_RANGE']) / Decimal(100) clk = imp * ctr conv_rate = randint(*conf['CONV_RATE_RANGE']) / Decimal(100) conv = clk * conv_rate conv_value = conv * randint(*conf['CONV_VALUE_RANGE']) / Decimal(100) return { 'imp': imp.quantize(Decimal('1')), 'imp_value': imp_value, 'clk': clk.quantize(Decimal('1')), 'conv': conv.quantize(Decimal('1')), 'conv_value': conv_value, 'data_cost_value': data_cost_value, 'commission_value': commission_value, }
def campaign_time_spent_ratio(campaign): """ Calculate part of campaign that has elapsed :return: Ratio between 0.0 and 1.0 :rtype: Decimal """ campaign_duration = int((campaign.end_UTC - campaign.start_UTC).total_seconds()) campaign_elapsed = int((datetime.utcnow() - campaign.start_UTC).total_seconds()) if campaign_elapsed < 0: return Decimal(0) return Decimal(campaign_elapsed) / campaign_duration
def test_strategy_overall(client, fill_db): ''' Tries to save strategy without required fields, Check errors and fill inputs with proper data. Saves strategy and checks UI and DB. ''' EDITED_STRATEGY = { 'name': 'Strategy Edited', 'budget': '50', 'budget-daily': '20', } ERRORS = { 'name_required': 'Strategy name: This field is required.', 'budget_required': 'Total strategy budget: This field is required.', } INPUTS = ['name', 'budget', 'budget-daily'] utils.go_to_step(client, 'overall', existing=True) # Clear all inputs for input_name in INPUTS: client.get_input(input_name).clear() # Try to save and check if correct errors are displayed client.click_on_class('button-save-changes') client.wait_for_modal() modal_errors = client.get_modal_errors() assert len(modal_errors) == len(ERRORS) for key in ERRORS.keys(): assert ERRORS[key] in modal_errors client.close_modal() # Fill inputs with proper data for input_name in INPUTS: client.send_keys(input_name, EDITED_STRATEGY[input_name]) # Save again and check UI and DB utils.save_and_return_to_step(client) for input_name in INPUTS: assert client.get_input_val(input_name) == EDITED_STRATEGY[input_name] strategy = Strategy.objects.all()[0] assert strategy.name == EDITED_STRATEGY['name'] assert strategy.budget_total == Decimal(EDITED_STRATEGY['budget']) assert strategy.budget_daily == Decimal(EDITED_STRATEGY['budget-daily'])
def test_derivative_metrics(state_app, report_class, related_class, related_object_attr, imp_value, imp, clk, conv, conv_value, commission_value, data_cost_value): imp_value_total = imp_value + commission_value + data_cost_value net_earned = conv_value - imp_value_total report = report_class(time=datetime.utcnow(), imp=imp, imp_value=imp_value, clk=clk, conv=conv, conv_value=conv_value, commission_value=commission_value, data_cost_value=data_cost_value) report.related = related_class.objects.first() report.save() aggregation = report_class.objects.report_table(related_obj=getattr( report.related, related_object_attr), sort_by='imp') assert len(aggregation) == 1 report_data = aggregation[0] ecpm = ctr = ecpc = ecpa = conv_rate = roi = Decimal(0) if imp_value: roi = (conv_value - imp_value_total) / imp_value_total * 100 if clk: ecpc = imp_value_total / clk conv_rate = conv / clk * 100 if imp: ecpm = imp_value_total / imp * 1000 ctr = clk / imp * 100 if conv: ecpa = imp_value_total / conv prec = Decimal('1.0000000') for metric in [ 'ecpc', 'ecpa', 'ecpm', 'ctr', 'conv_rate', 'roi', 'net_earned' ]: a = report_data[metric].quantize(prec) b = locals().get(metric).quantize(prec) assert a == b
def campaign_statuses(creative_statuses): '''Campaigns with all possible statuses''' campaign_finished = {'name': 'Campaign finished', 'account': 'acc', 'start_UTC': utcnow_with_timedelta(days=-7), 'end_UTC': utcnow_with_timedelta(days=-3), 'budget_total': 2000, 'budget_spent': 2000, 'landing_site': 'http://www.google.com/'} campaign_running = {'name': 'Campaign running', 'account': 'acc', 'start_UTC': utcnow_with_timedelta(days=-4), 'end_UTC': utcnow_with_timedelta(days=3), 'budget_total': 8000, 'landing_site': 'http://www.google.com/'} campaign_scheduled = {'name': 'Campaign scheduled', 'account': 'acc', 'start_UTC': utcnow_with_timedelta(days=10), 'end_UTC': utcnow_with_timedelta(days=13), 'budget_total': 1000, 'landing_site': 'http://www.google.com/'} strategy_a = {'name': 'Strategy A', 'campaign': 'Campaign finished', 'budget_total': 1000, 'budget_bid_CPM': Decimal('0.1')} strategy_b = {'name': 'Strategy B', 'campaign': 'Campaign running', 'budget_total': 0, 'budget_bid_CPM': Decimal('0.1')} strategy_c = {'name': 'Strategy C', 'campaign': 'Campaign scheduled', 'budget_total': 100, 'budget_bid_CPM': Decimal('0.1')} setup = creative_statuses setup.setup_landing_pages() setup.setup_campaigns([campaign_finished, campaign_running, campaign_scheduled]) setup.setup_strategies([strategy_a, strategy_b, strategy_c]) ADVERTS = [ {'name': 'Ad audited', 'strategy': 'Strategy A', 'creative': 'Image audited'}, {'name': 'Ad audit pending', 'strategy': 'Strategy B', 'creative': 'Image audit pending'}, {'name': 'Ad audit rejected', 'strategy': 'Strategy B', 'creative': 'Image audit rejected'}, {'name': 'Ad audit blocked', 'strategy': 'Strategy C', 'creative': 'Image audit blocked'}, {'name': 'Ad audit expired', 'strategy': 'Strategy C', 'creative': 'Image audit expired'} ] for advert in ADVERTS: advert.update({'url': 'http://www.google.com/'}) setup.setup_adverts([advert]) call_command('rebuild_index', interactive=False) return setup
def test_aggregate_dateranges(state_app, report_class, related_class, related_obj_attr): related = related_class.objects.first() for (dt, data_cost_value, imp, imp_value, clk, conv, conv_value) in REPORT_DATA: report = report_class( time=dt, imp=imp, imp_value=imp_value, clk=clk, conv=conv, conv_value=conv_value, data_cost_value=data_cost_value, ) report.related = related report.save() def check_aggregation(start_date, end_date, imp, imp_vt): ''' asserts imp and imp_value_total ''' [aggregation] = report_class.objects.report_table( related_obj=getattr(related, related_obj_attr), sort_by='imp', start_date=start_date, end_date=end_date, ) assert aggregation['imp'] == imp assert aggregation['imp_value_total'] == imp_vt # DATERANGE: 2014-04-01 - 2014-04-01 check_aggregation( start_date=DT0.date(), end_date=DT0.date(), imp=Decimal('77'), imp_vt=Decimal('325'), ) # DATERANGE: 2014-04-01 - 2014-04-02 check_aggregation( start_date=DT0.date(), end_date=DT2.date(), imp=Decimal('106'), imp_vt=Decimal('412'), )
def test_strategy_set_period_budgets(self, rc, period_budgets_app): ''' Test setting strategy budgets in Redis ''' strategy = Strategy.objects.first() strategy.is_distributed_evenly = True strategy.save() assert strategy.state.is_running is True # Save period budgets saved_budgets = Strategy.reset_period_budgets(rc) # Check if they were saved retrieved_budgets = rc.hgetall(Strategy.period_budgets_key) assert len(retrieved_budgets) == len(saved_budgets) assert strategy.public_id in retrieved_budgets assert Decimal(retrieved_budgets[strategy.public_id]) == \ saved_budgets[strategy.public_id] # this should take strategy off distribute evenly loop strategy.is_distributed_evenly = False strategy.save() # Try to remove them and check if they were removed saved_budgets = Strategy.reset_period_budgets(rc) assert rc.hgetall(Strategy.period_budgets_key) == {}, "Period budgets should be cleared!"
def test_edit_campain_conversion(client, fill_db): conv_data = { 'name': 'Here comes the conversion', 'value': '5', } go_to_campaign_step(client, 'conversion') for item in ('name', 'value'): # Clear input input = client.get_input('conversion-%s' % item) input.clear() modal_errors = save_with_errors(client) assert ERRORS['conversion_%s_required' % item] in modal_errors assert client.has_class(input, 'input-error') is True client.close_modal() # Write proper value client.send_keys(input, conv_data['%s' % item]) save_and_return(client, 'conversion') # Check UI and DB assert client.get_input('conversion-name').get_attribute('value') == conv_data['name'] assert client.get_input('conversion-value').get_attribute('value') == conv_data['value'] campaign = Campaign.objects.get(name='I\'m a fruit') assert campaign.conversion_def.name == conv_data['name'] assert campaign.conversion_def.value == Decimal(conv_data['value'])
def audit_app(basic_fixture): setup = DatabaseDataFactory() setup.setup_accounts() setup.setup_users() landing_pages = default_landing_page + \ [{'owner': 'acc', 'url': 'http://www.onet.com/'}] setup.setup_landing_pages(landing_pages) campaigns = default_campaign + [{ 'name': 'Meat', 'account': 'acc', 'budget_total': 8000, 'start_UTC': '2013-01-01T00:00', 'end_UTC': '2013-01-31T00:00', 'landing_site': 'http://www.onet.com/' }] setup.setup_campaigns(campaigns) strategies = default_strategies + [{ 'name': 'Roast beef', 'campaign': 'Meat', 'budget_total': 67676, 'budget_bid_CPM': Decimal('0.1') }] setup.setup_strategies(strategies) setup.setup_creative_images() return setup
def db_round(dec): ''' Return decimal rounded to the precision that tolerates cummulative differences of precision in Python and Postgres. ''' prec = Decimal('1e-14') # Use precision that is 'good enough'. return dec.quantize(prec)
def test_period_budget(bidding_periods_app, budget_daily, budget_daily_spent, budget_total, budget_total_spent, ratio, now, period_budget): """ Check value of budget with different values of daily and total budget and daily and total spend. """ class MyStrategy(TestStrategy): def bidding_periods_ratio(self): return self.__bidding_periods_ratio def set_bidding_periods_ratio(self, ratio): self.__bidding_periods_ratio = ratio campaign = Campaign.objects.all().first() campaign.end_UTC = datetime(2014, 10, 21, 01, 00, 00) campaign.save() strategy = MyStrategy( name='Strategy Cool', campaign=campaign, budget_total=budget_total, budget_daily=budget_daily, budget_bid_CPM=0.2 ) strategy.set_bidding_periods_ratio(ratio) strategy.budget_spent = budget_total_spent strategy.budget_daily_spent = budget_daily_spent assert strategy.period_budget(now) == Decimal(period_budget)
def test_aggregate_correctnes(state_app, report_class, related_class, related_object_attr, imp_value, imp, clk, conv, conv_value, imp_value_total, data_cost_value): now = datetime.utcnow() later = now + timedelta(hours=1, minutes=13) related = related_class.objects.first() report1 = report_class(time=now, imp_value=imp_value[0], imp=imp[0], clk=clk[0], conv=conv[0], conv_value=conv_value[0], data_cost_value=data_cost_value[0]) report1.related = related report1.save() report2 = report_class(time=later, imp_value=imp_value[1], imp=imp[1], clk=clk[1], conv=conv[1], conv_value=conv_value[1], data_cost_value=data_cost_value[1]) report2.related = related report2.save() aggregation = report_class.objects.report_table( related_obj=getattr(related, related_object_attr), start_date=date.today(), end_date=date.today() + timedelta(days=1), sort_by='imp', ) assert len(aggregation) == 1 report_data = aggregation[0] # All values needs to be cast to string, due to different precision # available, and the fact, that sometimes, I got a little more digits # when casting Decimal to float, than from operations on floats alone ecpm = ctr = ecpc = conv_rate = roi = Decimal(0) if sum(imp_value_total): numerator = sum(conv_value) - sum(imp_value_total) denominator = sum(imp_value_total) roi = (numerator / denominator) * 100 if sum(clk): ecpc = sum(imp_value_total) / sum(clk) conv_rate = (sum(conv) / sum(clk)) * 100 if sum(imp): ecpm = (sum(imp_value_total) / sum(imp)) * 1000 ctr = (sum(clk) / sum(imp)) * 100 assert db_round(report_data['ecpm']) == db_round(ecpm) assert db_round(report_data['ctr']) == db_round(ctr) assert db_round(report_data['ecpc']) == db_round(ecpc) assert db_round(report_data['conv_rate']) == db_round(conv_rate) assert db_round(report_data['roi']) == db_round(roi)
def to_precision(cls, dec): ''' Return rounded decimal for easy comparisions. :param Decimal dec: decimal to quantize :return Decimal: copy of dec, quantized to class precision ''' precision = Decimal('0.1')**cls.decimal_places return dec.quantize(precision)
def total_paid(self): """ Sum of payments account made. :returns: money balance for a given account :rtype: Decimal """ return self.payment_set.aggregate( sum=Sum('amount'))['sum'] or Decimal(0)
def period_validation_app(app): strategies = [ {'name': 'Hello this is Citrus', 'campaign': 'I\'m a fruit', 'budget_total': 12345, 'budget_daily': 12345, 'budget_bid_CPM': Decimal('0.2')} ] app.setup.setup_landing_pages() app.setup.setup_campaigns_running() app.setup.setup_strategies(strategies) return app
def fake_campaign_report(self, campaign): """Fake all reports related to Campaign and Strategy model for a single campaign""" def total_spent(metrics_dict): return (metrics_dict['imp_value'] + metrics_dict['data_cost_value'] + metrics_dict['commission_value']) campaign_time_spent = Decimal(campaign_time_spent_ratio(campaign)) campaign_budget_left = campaign.budget_total * campaign_time_spent campaign_metrics = { 'imp': 0, 'imp_value': Decimal('0'), 'clk': 0, 'conv': 0, 'conv_value': Decimal('0'), 'data_cost_value': Decimal('0'), 'commission_value': Decimal('0'), } for strategy in campaign.strategy_set.all(): strategy_spent = strategy.budget_total * campaign_time_spent effective_spent = min(campaign_budget_left, strategy_spent) strategy_metrics = self.fake_strategy_report(strategy, effective_spent) if strategy_metrics: reported_spent = total_spent(strategy_metrics) campaign_budget_left -= reported_spent strategy.budget_spent = reported_spent strategy.save() for metric, value in strategy_metrics.iteritems(): campaign_metrics[metric] += value campaign_spent = total_spent(campaign_metrics) campaign.budget_spent = campaign_spent campaign.save() self.create_campaign_reports(campaign, campaign_metrics)
def test_save_model_spending(self, bidding_app): ''' save_object_spending gets django model object and saves given spending value and spending time ''' saved_strat = bidding_app.models['strategy']['Hello this is Citrus'] saved_strat.save_spending(5, 1) saved_strat.save_daily_spending(1) strategy = Strategy.objects.get(pk=saved_strat.pk) assert strategy.budget_spent == Decimal('5') / offset assert strategy.budget_daily_spent == Decimal('1') / offset assert strategy.budget_spent_commission == Decimal('1') / offset saved_camp = bidding_app.models['campaign']['I\'m a fruit'] saved_camp.save_spending(5, 1) campaign = Campaign.objects.get(pk=saved_camp.pk) assert campaign.budget_spent == Decimal('5') / offset assert campaign.budget_spent_commission == Decimal('1') / offset
def test_save_spendings(self, db_factory_four_strategies): ''' save spendings takes spendings generated by get_spendings function and stores them in database via django active record. ''' strategies = db_factory_four_strategies.models['strategy'] strat_obj_spends = { strategies['Hello this is Citrus'].public_id: (30, 3, 123), strategies['han i has a pumpkin?'].public_id: (40, 4, 321), strategies['Strategy 3'].public_id: (1, 1, 31), } saved_models = Strategy.save_spendings(strat_obj_spends) assert len(saved_models) == 3 strat1 = Strategy.objects.get(pk=strategies['Hello this is Citrus'].pk) strat2 = Strategy.objects.get(pk=strategies['han i has a pumpkin?'].pk) strat3 = Strategy.objects.get(pk=strategies['Strategy 3'].pk) assert strat1.budget_spent == Decimal('30') / offset assert strat1.budget_spent_commission == Decimal('3') / offset assert strat2.budget_spent == Decimal('40') / offset assert strat2.budget_spent_commission == Decimal('4') / offset assert strat3.budget_spent == Decimal('1') / offset assert strat3.budget_spent_commission == Decimal('1') / offset
def test_bidding_periods_nonzero(bidding_periods_app, strategy_bid, periods, ads, nonzero_periods): strategy = Strategy.objects.get(name='Hello this is Citrus') strategy.is_day_parted = True strategy.budget_bid_CPM = Decimal(strategy_bid) strategy.save() setup_bidding_periods(strategy, periods) setup_bidding_ads(strategy, ads) calculated_period_ids = [p.pk for p in strategy._bidding_periods_nonzero()] expected_period_ids = [p.pk for p in get_expected_periods(nonzero_periods)] assert sorted(calculated_period_ids) == sorted(expected_period_ids)
def test_update_bidder_spendings(redisdb_spendings, bidding_app): """ Create a redis spending entries for campaign. Check redis pubsub channel for correct message. """ # no point in this test if we don't have any campaign here assert Campaign.objects.count() > 0 # let's patch publish method to intercept published message with patch.object(update_bidder_spendings.rd, 'publish'): for campaign in Campaign.objects.all(): redisdb_spendings.hset( adserving.bidder.spendings.spend_camp_key, campaign.public_id, Decimal('0.8') ) redisdb_spendings.hset( adserving.bidder.spendings.spend_camp_key, campaign.public_id + adserving.bidder.spendings.string_commission, Decimal('0.2') ) update_bidder_spendings() channel, message = update_bidder_spendings.rd.publish.call_args[0] message = simplejson.loads(message, use_decimal=True) assert adserving.bidder.spendings.spend_account_key in message assert adserving.bidder.spendings.spend_camp_key in message assert adserving.bidder.spendings.spend_strat_key in message assert adserving.bidder.spendings.spend_strat_daily_key in message assert adserving.bidder.spendings.spend_strat_period_key in message # message should have twice that much of entries for campaigns assert len(message[adserving.bidder.spendings.spend_camp_key]) == 2 * Campaign.objects.count() for account, value in message[adserving.bidder.spendings.spend_account_key].iteritems(): count = Campaign.objects.filter(account__id_random=account).count() # value should be equal to campaign numbers account holds (0.8 for spend, and 0.2 for commission above) assert value == count * adserving.bidder.spendings.cast_dbbid_to_CPM(1)
def append_dollar(decimal_val): ''' Appends dollar sign to the Decimal value (rounded to two places) and returns it as a string. :rtype: string (i.e '$12.45' or '-$12.45') or None (if value is None) ''' if decimal_val is None: return None rounded_val = decimal_val.quantize(Decimal('0.01')) if rounded_val >= 0: return '$%s' % rounded_val return '-$%s' % abs(rounded_val)
def test_bidding_periods_ratio_not_day_parted(bidding_periods_app): ''' Test if bidding_periods_ratio is 1 for not day parted strategy ''' campaign = Campaign.objects.all().first() strategy = Strategy.objects.create( name='Strategy Cool', campaign=campaign, budget_total=12345, budget_daily=12345, budget_bid_CPM=Decimal('0.2'), is_day_parted=False ) assert strategy.bidding_periods_ratio() == 1
def setup_bidding_ads(strategy, ads): for index, ad in enumerate(ads): ad_db = Advert.objects.all()[index] if (ad['bid_type'] == 'custom'): ad_db._set_custom_bid_CPM(ad['value']) ad_db.save() elif (ad['bid_type'] == 'custom_parting'): for bid in ad['values']: period = BiddingPeriod.objects.get( start=bid['start'], end=bid['end'] ) AdvertPeriod.objects.create( advert=ad_db, period=period, custom_bid_CPM=Decimal(bid['value']) )
def db_factory_two_camps(bidding_app): """ Extends bidding_app fixture by adding another campaign. In result database has two campaigns. """ campaigns = [ {'name': 'I\'m a ninja', 'account': 'acc', 'budget_total': 8000, 'start_UTC': '2013-01-01T00:00', 'end_UTC': '2013-01-31T00:00', 'landing_site': 'http://www.google.com/'}, ] strategies = [ {'name': 'Hello this is ninja', 'campaign': 'I\'m a ninja', 'budget_total': 12345, 'budget_bid_CPM': Decimal('0.2')}, ] bidding_app.setup_campaigns(campaigns) bidding_app.setup_strategies(strategies) return bidding_app
def period_budget(self, now): ''' Calculate the period budget based on budget left and period length :param datetime now: UTC datetime containing current time :returns amount of money to spend in current period :rtype Decimal ''' effective_budget = self.budget_left if not self.budget_daily \ else min(self.budget_daily_left, self.budget_left) periods_left = self.periods_left(now) if not periods_left: return Decimal(0) # Period budgets are based on real time so they are ok to # be constructed from floats (that leads to 'ugly' # decimals). return (effective_budget / UnsafeDecimal(periods_left) * UnsafeDecimal(self.bidding_periods_ratio()))
def bidding_periods_app(app): strategies = [ {'name': 'Hello this is Citrus', 'campaign': 'I\'m a fruit', 'budget_total': 12345, 'budget_daily': 12345, 'budget_bid_CPM': Decimal('0.2')} ] creatives = [ {'name': 'creative_image_1', 'owner': 'acc', 'width': 300, 'height': 250, 'image': 'test_creative.jpg'}, {'name': 'creative_image_2', 'owner': 'acc', 'width': 600, 'height': 500, 'image': 'test_creative.jpg'}, ] app.setup.setup_landing_pages() app.setup.setup_campaigns_running() app.setup.setup_strategies(strategies) app.setup.setup_creative_images(creatives) strategy = app.setup.models['strategy']['Hello this is Citrus'] creative1 = app.setup.models['creative']['creative_image_1'] creative2 = app.setup.models['creative']['creative_image_2'] Advert.objects.create( strategy=strategy, creative=creative1, landing_site=Site.objects.get( url='http://www.google.com/', owner=strategy.campaign.account) ) Advert.objects.create( strategy=strategy, creative=creative2, landing_site=Site.objects.get( url='http://www.google.com/', owner=strategy.campaign.account) ) return app