def test_raises_invalid_cohort_for_any_metric(self): self.cohort.validated = False self.session.commit() for name, metric in metric_classes.iteritems(): if not metric.show_in_ui: continue parameters = { 'name': '{0} - test'.format(name), 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': name, 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-02 00:00:00', 'individualResults': True, 'aggregateResults': False, 'aggregateSum': False, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } try: RunReport(parameters, user_id=self.owner_user_id) except InvalidCohort: continue assert_true(False)
def test_user_id_assigned_properly(self): parameters = { 'name': 'Bytes - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'BytesAdded', 'namespaces': '0,1,2', 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-02 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } jr = RunReport(parameters, user_id=self.owner_user_id) jr.task.delay(jr).get() self.session.commit() # executing directly the code that will be run by the scheduler recurring_reports() # make sure all report nodes have a user_id no_user_id = self.session.query(func.count(ReportStore)) \ .filter(ReportStore.user_id == None) \ .one()[0] assert_equals(no_user_id, 0)
def test_basic_response(self): desired_responses = [{ 'name': 'Edits - test', 'cohort': { 'id': self.test_cohort_id, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-06-01', 'end_date': '2013-09-01', 'individualResults': True, 'aggregateResults': False, 'aggregateSum': False, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, }] jr = RunReport(desired_responses, user_id=self.test_user_id) results = jr.task.delay(jr).get() result_key = self.session.query(PersistentReport)\ .filter(PersistentReport.id == jr.children[0].persistent_id)\ .one()\ .result_key results = results[result_key] # TODO: figure out why one of the resulting wiki_user_ids is None here assert_equals( results[Aggregation.IND][0][self.test_mediawiki_user_id]['edits'], 2, )
def test_aggregated_response_bytes_added(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'BytesAdded', 'namespaces': [0], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-03 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } jr = RunReport(parameters, user_id=self.owner_user_id) results = jr.task.delay(jr).get() self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key results = results[result_key] assert_equals( results[Aggregation.IND][self.editor(0)]['net_sum'], -90, ) assert_equals( results[Aggregation.SUM]['positive_only_sum'], 140, )
def test_basic_response(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-02 00:00:00', 'individualResults': True, 'aggregateResults': False, 'aggregateSum': False, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } jr = RunReport(parameters, user_id=self.owner_user_id) results = jr.task.delay(jr).get() self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key results = results[result_key] # TODO: figure out why one of the resulting wiki_user_ids is None here assert_equals( results[Aggregation.IND][self.editor(0)]['edits'], 2, )
def test_aggregated_response_bytes_added(self): desired_responses = [{ 'name': 'Edits - test', 'cohort': { 'id': self.test_cohort_id, }, 'metric': { 'name': 'BytesAdded', 'namespaces': [0, 1, 2], 'start_date': '2013-06-01', 'end_date': '2013-09-01', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, }] jr = RunReport(desired_responses, user_id=self.test_user_id) results = jr.task.delay(jr).get() result_key = self.session.query(PersistentReport)\ .filter(PersistentReport.id == jr.children[0].persistent_id)\ .one()\ .result_key results = results[result_key] assert_equals( results[Aggregation.IND][0][self.test_mediawiki_user_id]['net_sum'], 6, ) assert_equals( results[Aggregation.SUM]['positive_only_sum'], 150, )
def test_empty_response(self): """ Case where user tries to submit form with no cohorts / metrics should be handled client side server side an exception will be thrown if RunReport object cannot be created """ RunReport({}, user_id=self.owner_user_id)
def inject_and_fetch_recurrent_run(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-03 00:00:00', 'individualResults': True, 'aggregateResults': False, 'aggregateSum': False, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, 'recurrent': True, } jr = RunReport(parameters, user_id=self.owner_user_id) jr.task.delay(jr).get() self.session.commit() # executing directly the code that will be run by the scheduler recurring_reports() recurrent_runs = self.session.query(ReportStore) \ .filter(ReportStore.recurrent_parent_id == jr.persistent_id) \ .all() return recurrent_runs
def test_invalid_metric(self): run_report = RunReport() run_report.parse_request([{ 'name': 'Edits - test', 'cohort': { 'id': self.test_cohort_id, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': 'blah blah', }, }])
def test_run_report_repr(self): run_report = RunReport( { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', }, }, user_id=self.owner_user_id) assert_true(str(run_report).find('RunReport') >= 0)
def test_run_report_finish(self): run_report = RunReport( { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', }, }, user_id=self.owner_user_id) result = run_report.finish(['aggregate_result']) assert_equals(result[run_report.result_key], 'aggregate_result')
def test_lots_of_concurrent_requests(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'BytesAdded', 'namespaces': '0,1,2', 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-02 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } reports = [] # NOTE: you can make this loop as much as you'd like if celery # is allowed enough concurrent workers, set via CELERYD_CONCURRENCY trials = 3 for i in range(trials): jr = RunReport(parameters, user_id=self.owner_user_id) reports.append((jr, jr.task.delay(jr))) successes = 0 for jr, delayed in reports: try: results = delayed.get() self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key results = results[result_key] if results[Aggregation.SUM]['positive_only_sum'] == 140: successes += 1 except SoftTimeLimitExceeded: print('Timeout expired during this task.') except Exception: print('An exception occurred during this task.') raise print('Successes: {0}'.format(successes)) assert_true(successes == trials, 'all of the trials must succeed')
def test_aggregated_response_namespace_edits_with_timeseries(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:20:00', 'end_date': '2013-03-01 00:00:00', 'timeseries': TimeseriesChoices.MONTH, 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } jr = RunReport(parameters, user_id=self.owner_user_id) results = jr.task.delay(jr).get() self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key results = results[result_key] key = results[Aggregation.IND][self.editor(0)]['edits'].items()[0][0] assert_equals(key, '2013-01-01 00:20:00') assert_equals( results[Aggregation.SUM]['edits'].items()[0][0], '2013-01-01 00:20:00', ) assert_equals( results[Aggregation.SUM]['edits']['2013-01-01 00:20:00'], 8, ) assert_equals( results[Aggregation.SUM]['edits']['2013-02-01 00:00:00'], 2, )
def test_wiki_cohort_runs(self): self.create_wiki_cohort() # give the WikiCohort all the users of self.cohort, for easy testing self.session.execute(WikiUserStore.__table__.update().values( validating_cohort=self.basic_wiki_cohort.id).where( WikiUserStore.validating_cohort == self.cohort.id)) self.session.execute(CohortWikiUserStore.__table__.update().values( cohort_id=self.basic_wiki_cohort.id).where( CohortWikiUserStore.cohort_id == self.cohort.id)) self.cohort = self.basic_wiki_cohort parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-02 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': True, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, } jr = RunReport(parameters, user_id=self.owner_user_id) results = jr.task.delay(jr).get() self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key results = results[result_key] assert_equals( results[Aggregation.IND][self.editor(0)]['edits'], 2, ) assert_equals( results[Aggregation.SUM]['edits'], 4, )
def test_many_parallel_runs(self): parameters = { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-01-03 00:00:00', 'individualResults': True, 'aggregateResults': False, 'aggregateSum': False, 'aggregateAverage': False, 'aggregateStandardDeviation': False, }, 'recurrent': True, } jr = RunReport(parameters, user_id=self.owner_user_id, created=datetime.today() - timedelta(days=self.total_runs)) jr.task.delay(jr).get() self.session.commit() # executing directly the code that will be run by the scheduler recurring_reports() recurrent_runs = self.session.query(ReportStore) \ .filter(ReportStore.recurrent_parent_id == jr.persistent_id) \ .all() successful_runs = filter(lambda x: x.status == 'SUCCESS', recurrent_runs) # make sure we have one and no more than one recurrent run assert_equal(len(successful_runs), self.total_runs)
def test_invalid_metric(self): jr = RunReport( { 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, }, 'metric': { 'name': 'NamespaceEdits', 'start_date': 'blah', }, }, user_id=self.owner_user_id) results = jr.task.delay(jr).get() print results self.session.commit() result_key = self.session.query(ReportStore) \ .get(jr.persistent_id) \ .result_key assert_true( results[result_key]['FAILURE'].find( 'Edits was incorrectly configured') >= 0, )
def reports_request(): """ Renders a page that facilitates kicking off a new report """ if request.method == 'GET': return render_template('report.html') else: desired_responses = json.loads(request.form['responses']) recurrent = json.loads(request.form.get('recurrent', 'false')) for parameters in desired_responses: parameters['recurrent'] = recurrent # NOTE: this is not a mistake. Currently recurrent => public on creation parameters['public'] = recurrent # Encode cohort description for the case it contains special characters if ('description' in parameters['cohort'] and parameters['cohort']['description'] is not None): encoded_description = parameters['cohort']['description'].encode('utf-8') parameters['cohort']['description'] = encoded_description jr = RunReport(parameters, user_id=current_user.id) jr.task.delay(jr) return json_redirect(url_for('reports_index'))
def test_empty_response(self): # TODO: handle case where user tries to submit form with no cohorts / metrics jr = RunReport([], user_id=self.test_user_id) result = jr.task.delay(jr).get() assert_equals(result, [])
def test_run_report_repr(self): run_report = RunReport([]) assert_true(str(run_report).find('RunReport') >= 0)
def test_run_report_finish(self): run_report = RunReport([]) result = run_report.finish([]) assert_equals(result[run_report.result_key], 'Finished')
def test_invalid_report(self): RunReport({})