def test_filters_by_project_type(self): project1 = ProjectFactory.create() project2 = ProjectFactory.create() exp1 = ExperimentFactory.create(projects=[project1]) ExperimentFactory.create(projects=[project2]) data = {"projects": project1.id} filter = ExperimentFilterset(data=data, queryset=Experiment.objects.all()) self.assertTrue(filter.is_valid()) self.assertCountEqual(filter.qs, [exp1]) self.assertEqual(filter.get_project_display_value(), project1)
def test_project_form_does_not_check_name_duplicate_when_editing(self): project = ProjectFactory.create() form = ProjectForm({"name": project.name}, instance=project) self.assertTrue(form.is_valid()) form.save()
def test_doesnt_set_slug_for_existing_instance(self): project = ProjectFactory.create(name="Old Name", slug="old-slug") form = self.Form({"name": "New Name"}, instance=project) self.assertTrue(form.is_valid()) project = form.save() self.assertEqual(project.name, "New Name") self.assertEqual(project.slug, "old-slug")
def test_project_form_checks_for_name_duplicates_for_new_project(self): existing_project = ProjectFactory.create() form = ProjectForm({"name": existing_project.name}) self.assertFalse(form.is_valid()) self.assertIn("name", form.errors)
def projects(self, create, extracted, **kwargs): if not create: return if extracted is None: extracted = [ProjectFactory.create() for i in range(3)] self.projects.add(*extracted)
def test_filters_by_multiple_project_type(self): project1 = ProjectFactory.create() project2 = ProjectFactory.create() project3 = ProjectFactory.create() exp1 = ExperimentFactory.create(projects=[project1, project2]) exp2 = ExperimentFactory.create(projects=[project2]) ExperimentFactory.create(projects=[project3]) data = QueryDict(f"projects={project1.id}&projects={project2.id}") filter = ExperimentFilterset(data=data, queryset=Experiment.objects.all()) self.assertTrue(filter.is_valid()) self.assertCountEqual(filter.qs, [exp1, exp2]) display_value = filter.get_project_display_value() self.assertIn(project1.name, display_value) self.assertIn(project2.name, display_value)
def test_list_view_filters_and_orders_experiments(self): user_email = "*****@*****.**" ordering = "latest_change" filtered_channel = Experiment.CHANNEL_CHOICES[1][0] filtered_owner = UserFactory.create() filtered_project = ProjectFactory.create() filtered_status = Experiment.STATUS_DRAFT filtered_version = Experiment.VERSION_CHOICES[1][0] for i in range(10): ExperimentFactory.create_with_status( firefox_channel=filtered_channel, firefox_version=filtered_version, owner=filtered_owner, project=filtered_project, target_status=filtered_status, ) for i in range(10): ExperimentFactory.create_with_status( random.choice(Experiment.STATUS_CHOICES)[0] ) filtered_ordered_experiments = Experiment.objects.filter( firefox_channel=filtered_channel, firefox_version=filtered_version, owner=filtered_owner, project=filtered_project, status=filtered_status, ).order_by(ordering) response = self.client.get( "{url}?{params}".format( url=reverse("home"), params=urlencode( { "firefox_channel": filtered_channel, "firefox_version": filtered_version, "ordering": ordering, "owner": filtered_owner.id, "project": filtered_project.id, "status": filtered_status, } ), ), **{settings.OPENIDC_EMAIL_HEADER: user_email}, ) context = response.context[0] self.assertEqual(response.status_code, 200) self.assertEqual( list(context["experiments"]), list(filtered_ordered_experiments) )
def projects(self, create, extracted, **kwargs): if not create: # Simple build, do nothing. return if isinstance(extracted, Iterable): # A list of groups were passed in, use them for project in extracted: self.projects.add(project) else: for i in range(3): self.projects.add(ProjectFactory.create())
def test_filters_by_project(self): project = ProjectFactory.create() for i in range(3): ExperimentFactory.create_with_status(Experiment.STATUS_DRAFT, project=project) ExperimentFactory.create_with_status(Experiment.STATUS_DRAFT) filter = ExperimentFilterset({"project": project.id}, queryset=Experiment.objects.all()) self.assertEqual(set(filter.qs), set(Experiment.objects.filter(project=project)))
def test_filters_by_no_project_type(self): project1 = ProjectFactory.create() exp1 = ExperimentFactory.create(projects=[]) ExperimentFactory.create(projects=[project1]) ExperimentFactory.create(projects=[project1]) data = QueryDict("projects=null") filter = ExperimentFilterset(data=data, queryset=Experiment.objects.all()) self.assertTrue(filter.is_valid()) self.assertCountEqual(filter.qs, [exp1]) display_value = filter.get_project_display_value() self.assertEqual("No Projects", display_value)
def test_view_creates_experiment(self): user_email = "*****@*****.**" project = ProjectFactory.create() data = { "type": Experiment.TYPE_PREF, "project": project.id, "name": "A new experiment!", "short_description": "Let us learn new things", "population_percent": "10", "firefox_version": Experiment.VERSION_CHOICES[-1][0], "firefox_channel": Experiment.CHANNEL_NIGHTLY, "client_matching": "en-us only please", "proposed_start_date": datetime.date.today(), "proposed_end_date": (datetime.date.today() + datetime.timedelta(days=1)), } response = self.client.post( reverse("experiments-create"), data, **{settings.OPENIDC_EMAIL_HEADER: user_email}, ) self.assertEqual(response.status_code, 302) experiment = Experiment.objects.get() self.assertEqual(experiment.status, experiment.STATUS_DRAFT) self.assertEqual(experiment.name, data["name"]) self.assertEqual(experiment.changes.count(), 1) change = experiment.changes.get() self.assertEqual(change.changed_by.email, user_email) self.assertEqual(change.old_status, None) self.assertEqual(change.new_status, experiment.STATUS_DRAFT)
def test_project_update_view_updates_project(self): project = ProjectFactory.create() headers = {settings.OPENIDC_EMAIL_HEADER: "*****@*****.**"} project_data = {"name": "New Name"} response = self.client.post( reverse("projects-update", kwargs={"slug": project.slug}), project_data, **headers ) updated_project = Project.objects.get(id=project.id) self.assertEqual(updated_project.name, project_data["name"]) self.assertRedirects( response, reverse("projects-detail", kwargs={"slug": updated_project.slug}), fetch_redirect_response=False, )
def setUp(self): super().setUp() ds_url = "{base}DS-123".format(base=settings.DS_ISSUE_HOST) bug_url = "{base}show_bug.cgi?id=123".format( base=settings.BUGZILLA_HOST) self.related_exp = ExperimentFactory.create() project = ProjectFactory.create() self.data = { "type": Experiment.TYPE_PREF, "name": "A new experiment!", "short_description": "Let us learn new things", "data_science_issue_url": ds_url, "owner": self.user.id, "analysis_owner": self.user.id, "engineering_owner": "Lisa the Engineer", "public_description": "Let us learn new public things", "related_to": [self.related_exp], "feature_bugzilla_url": bug_url, "projects": [project], }
def test_view_filters_by_project(self): user_email = "*****@*****.**" project = ProjectFactory.create() experiment1 = ExperimentFactory.create_with_status( Experiment.STATUS_DRAFT, name="a", projects=[project]) experiment2 = ExperimentFactory.create_with_status( Experiment.STATUS_DRAFT, name="b", projects=[project]) ExperimentFactory.create_with_variants() url = reverse("experiments-api-csv") response = self.client.get( f"{url}?projects={project.id}", **{settings.OPENIDC_EMAIL_HEADER: user_email}) self.assertEqual(response.status_code, 200) csv_data = response.content expected_csv_data = ExperimentCSVRenderer().render( ExperimentCSVSerializer([experiment1, experiment2], many=True).data, renderer_context={"header": ExperimentCSVSerializer.Meta.fields}, ) self.assertEqual(csv_data, expected_csv_data)
def test_list_view_filters_by_project_slug(self): project = ProjectFactory.create() project_experiments = [] # another projects experiments should be excluded for i in range(2): ExperimentFactory.create_with_variants() # started project experiments should be included for i in range(3): experiment = ExperimentFactory.create_with_variants( project=project) project_experiments.append(experiment) response = self.client.get(reverse('experiments-list'), {'project__slug': project.slug}) self.assertEqual(response.status_code, 200) json_data = json.loads(response.content) serialized_experiments = ExperimentSerializer( project.experiments.all(), many=True).data self.assertEqual(serialized_experiments, json_data)
def test_project_update_view_updates_project(self): project = ProjectFactory.create() headers = { settings.OPENIDC_EMAIL_HEADER: '*****@*****.**', } project_data = { 'name': 'New Name', } response = self.client.post( reverse('projects-update', kwargs={'slug': project.slug}), project_data, **headers) updated_project = Project.objects.get(id=project.id) self.assertEqual(updated_project.name, project_data['name']) self.assertEqual(updated_project.slug, 'new-name') self.assertRedirects( response, reverse('projects-detail', kwargs={'slug': updated_project.slug}), fetch_redirect_response=False, )
def test_serializer_outputs_expected_schema(self): project1 = ProjectFactory.create(name="b_project1") project2 = ProjectFactory.create(name="a_project2") experiment = ExperimentFactory.create_with_status( Experiment.STATUS_COMPLETE, countries=[], locales=[], recipe_slug="a-normandy-slug", normandy_id=123, other_normandy_ids=[], results_fail_to_launch=False, results_failures_notes="failure notes", platforms=[Experiment.PLATFORM_LINUX], is_high_population=True, projects=[project1, project2], ) # ensure expected_data has "string" if pref_type is json string pref_type = PrefTypeField().to_representation(experiment.pref_type) serializer = ExperimentSerializer(experiment) expected_data = { "client_matching": experiment.client_matching, "platforms": experiment.platforms, "end_date": JSTimestampField().to_representation(experiment.end_date), "experiment_url": experiment.experiment_url, "firefox_channel": experiment.firefox_channel, "firefox_min_version": experiment.firefox_min_version, "firefox_max_version": experiment.firefox_max_version, "name": experiment.name, "population": experiment.population, "population_percent": "{0:.4f}".format(experiment.population_percent), "pref_branch": experiment.pref_branch, "pref_name": experiment.pref_name, "pref_type": pref_type, "addon_experiment_id": experiment.addon_experiment_id, "addon_release_url": experiment.addon_release_url, "proposed_start_date": JSTimestampField().to_representation( experiment.proposed_start_date), "proposed_enrollment": experiment.proposed_enrollment, "proposed_duration": experiment.proposed_duration, "public_description": experiment.public_description, "slug": experiment.slug, "start_date": JSTimestampField().to_representation(experiment.start_date), "status": Experiment.STATUS_COMPLETE, "type": experiment.type, "normandy_slug": experiment.recipe_slug, "normandy_id": experiment.normandy_id, "other_normandy_ids": experiment.other_normandy_ids, "is_high_population": experiment.is_high_population, "variants": [ ExperimentVariantSerializer(variant).data for variant in experiment.variants.all() ], "locales": [], "countries": [], "changes": [ ExperimentChangeLogSerializer(change).data for change in experiment.changes.all() ], "results": { "results_url": None, "results_initial": None, "results_lessons_learned": None, "results_fail_to_launch": False, "results_recipe_errors": None, "results_restarts": None, "results_low_enrollment": None, "results_early_end": None, "results_no_usable_data": None, "results_failures_notes": "failure notes", "results_changes_to_firefox": None, "results_data_for_hypothesis": None, "results_confidence": None, "results_measure_impact": None, "results_impact_notes": None, }, "projects": ["a_project2", "b_project1"], } self.assertEqual(set(serializer.data.keys()), set(expected_data.keys())) self.assertEqual(serializer.data, expected_data)
def test_outputs_expected_schema_for_complete_experiment(self): application = NimbusExperiment.Application.DESKTOP probe_set = NimbusProbeSetFactory.create() feature_config = NimbusFeatureConfigFactory.create() project = ProjectFactory.create() experiment = NimbusExperimentFactory.create_with_status( NimbusExperiment.Status.COMPLETE, application=application, probe_sets=[probe_set], feature_config=feature_config, projects=[project], ) data = dict(NimbusExperimentChangeLogSerializer(experiment).data) branches_data = [dict(b) for b in data.pop("branches")] control_branch_data = dict(data.pop("reference_branch")) self.assertEqual( data, { "application": experiment.application, "channel": experiment.channel, "feature_config": { "name": feature_config.name, "slug": feature_config.slug, "description": feature_config.description, "application": feature_config.application, "owner_email": feature_config.owner_email, "schema": None, }, "firefox_min_version": experiment.firefox_min_version, "hypothesis": experiment.hypothesis, "is_paused": experiment.is_paused, "name": experiment.name, "owner": experiment.owner.email, "population_percent": str(experiment.population_percent), "probe_sets": [probe_set.slug], "projects": [project.slug], "proposed_duration": experiment.proposed_duration, "proposed_enrollment": experiment.proposed_enrollment, "public_description": experiment.public_description, "slug": experiment.slug, "status": experiment.status, "targeting_config_slug": experiment.targeting_config_slug, "total_enrolled_clients": experiment.total_enrolled_clients, }, ) self.assertEqual( control_branch_data, { "description": experiment.reference_branch.description, "feature_enabled": experiment.reference_branch.feature_enabled, "feature_value": experiment.reference_branch.feature_value, "name": experiment.reference_branch.name, "ratio": experiment.reference_branch.ratio, "slug": experiment.reference_branch.slug, }, ) for branch in experiment.branches.all(): self.assertIn( { "description": branch.description, "feature_enabled": branch.feature_enabled, "feature_value": branch.feature_value, "name": branch.name, "ratio": branch.ratio, "slug": branch.slug, }, branches_data, )
def test_get_project_display_value_returns_project_str(self): project = ProjectFactory.create() form = ExperimentFiltersetForm({"project": project.id}) self.assertEqual(form.get_project_display_value(), str(project))
def test_invalid_for_existing_slug_match(self): ProjectFactory(name="Unique Existing Name", slug="existing-slug") form = self.Form({"name": "Existing Slug"}) self.assertFalse(form.is_valid()) self.assertIn("name", form.errors)
def test_invalid_for_no_name_entered(self): ProjectFactory(name="Unique Existing Name", slug="existing-slug") form = self.Form({"name": ""}) self.assertFalse(form.is_valid()) self.assertIn("name", form.errors)
def test_changelog_values(self): experiment = Experiment() experiment.save() ds_url = "{base}DS-123".format(base=settings.DS_ISSUE_HOST) bug_url = "{base}show_bug.cgi?id=123".format( base=settings.BUGZILLA_HOST) related_exp = ExperimentFactory.create() project = ProjectFactory.create() data = { "type": Experiment.TYPE_PREF, "name": "A new experiment!", "short_description": "Let us learn new things", "data_science_issue_url": ds_url, "owner": self.user.id, "analysis_owner": self.user.id, "engineering_owner": "Lisa the Engineer", "public_description": "Let us learn new public things", "related_to": [related_exp], "feature_bugzilla_url": bug_url, "related_work": "Designs: https://www.example.com/myproject/", "projects": [project], } form = ExperimentOverviewForm(request=self.request, data=data, instance=experiment) self.assertTrue(form.is_valid()) experiment = form.save() latest_changes = experiment.changes.latest() expected_data = { "analysis_owner": { "display_name": "Data Science Owner", "new_value": experiment.analysis_owner.id, "old_value": None, }, "data_science_issue_url": { "display_name": "Data Science Issue URL", "new_value": "https://jira.example.com/browse/DS-123", "old_value": None, }, "engineering_owner": { "display_name": "Engineering Owner", "new_value": "Lisa the Engineer", "old_value": None, }, "feature_bugzilla_url": { "display_name": "Feature Bugzilla URL", "new_value": "https://bugzilla.allizom.org/show_bug.cgi?id=123", "old_value": None, }, "name": { "display_name": "Public Name", "new_value": "A new experiment!", "old_value": None, }, "owner": { "display_name": "Delivery Owner", "new_value": experiment.owner.id, "old_value": None, }, "projects": { "display_name": "Related Projects", "new_value": [{ "slug": project.slug }], "old_value": None, }, "public_description": { "display_name": "Public Description", "new_value": "Let us learn new public things", "old_value": None, }, "related_to": { "display_name": "Related Deliveries", "new_value": [related_exp.id], "old_value": None, }, "related_work": { "display_name": "Related Work URLs", "new_value": "Designs: https://www.example.com/myproject/", "old_value": None, }, "short_description": { "display_name": "Internal Description", "new_value": "Let us learn new things", "old_value": None, }, } self.maxDiff = None self.assertEqual(expected_data, latest_changes.changed_values)
def test_outputs_expected_schema_for_complete_experiment(self): application = NimbusExperiment.Application.DESKTOP feature_config = NimbusFeatureConfigFactory.create() project = ProjectFactory.create() primary_outcome = Outcomes.by_application(application)[0].slug secondary_outcome = Outcomes.by_application(application)[1].slug experiment = NimbusExperimentFactory.create_with_lifecycle( NimbusExperimentFactory.Lifecycles.ENDING_APPROVE_APPROVE, application=application, feature_config=feature_config, projects=[project], primary_outcomes=[primary_outcome], secondary_outcomes=[secondary_outcome], ) data = dict(NimbusExperimentChangeLogSerializer(experiment).data) branches_data = [dict(b) for b in data.pop("branches")] control_branch_data = dict(data.pop("reference_branch")) locales_data = data.pop("locales") countries_data = data.pop("countries") feature_config_data = data.pop("feature_config") published_dto_data = data.pop("published_dto") self.assertEqual( data, { "application": experiment.application, "channel": experiment.channel, "firefox_min_version": experiment.firefox_min_version, "hypothesis": experiment.hypothesis, "is_paused": experiment.is_paused, "name": experiment.name, "owner": experiment.owner.email, "population_percent": str(experiment.population_percent), "primary_outcomes": [primary_outcome], "projects": [project.slug], "proposed_duration": experiment.proposed_duration, "proposed_enrollment": experiment.proposed_enrollment, "public_description": experiment.public_description, "publish_status": experiment.publish_status, "results_data": None, "risk_brand": experiment.risk_brand, "risk_mitigation_link": experiment.risk_mitigation_link, "risk_partner_related": experiment.risk_partner_related, "risk_revenue": experiment.risk_revenue, "secondary_outcomes": [secondary_outcome], "slug": experiment.slug, "status": experiment.status, "status_next": experiment.status_next, "targeting_config_slug": experiment.targeting_config_slug, "total_enrolled_clients": experiment.total_enrolled_clients, }, ) self.assertEqual( published_dto_data.keys(), dict(NimbusExperimentSerializer(experiment).data).keys(), ) self.assertEqual( feature_config_data, { "name": feature_config.name, "slug": feature_config.slug, "description": feature_config.description, "application": feature_config.application, "owner_email": feature_config.owner_email, "schema": feature_config.schema, }, ) self.assertEqual( set(locales_data), set(experiment.locales.all().values_list("code", flat=True)), ) self.assertEqual( set(countries_data), set(experiment.countries.all().values_list("code", flat=True)), ) self.assertEqual( control_branch_data, { "description": experiment.reference_branch.description, "feature_enabled": experiment.reference_branch.feature_enabled, "feature_value": experiment.reference_branch.feature_value, "name": experiment.reference_branch.name, "ratio": experiment.reference_branch.ratio, "slug": experiment.reference_branch.slug, }, ) for branch in experiment.branches.all(): self.assertIn( { "description": branch.description, "feature_enabled": branch.feature_enabled, "feature_value": branch.feature_value, "name": branch.name, "ratio": branch.ratio, "slug": branch.slug, }, branches_data, )
def test_serializer_outputs_expected_schema(self): country1 = CountryFactory(code="CA", name="Canada") locale1 = LocaleFactory(code="da", name="Danish") project = ProjectFactory.create() experiment = ExperimentFactory.create(locales=[locale1], countries=[country1], projects=[project]) related_exp = ExperimentFactory.create() experiment.related_to.add(related_exp) serializer = ChangeLogSerializer(experiment) risk_tech_description = experiment.risk_technical_description expected_data = { "type": experiment.type, "owner": experiment.owner.id, "name": experiment.name, "short_description": experiment.short_description, "related_work": experiment.related_work, "related_to": [related_exp.id], "proposed_start_date": str(experiment.proposed_start_date), "proposed_duration": experiment.proposed_duration, "proposed_enrollment": experiment.proposed_enrollment, "design": experiment.design, "addon_experiment_id": experiment.addon_experiment_id, "addon_release_url": experiment.addon_release_url, "pref_name": experiment.pref_name, "pref_type": experiment.pref_type, "pref_branch": experiment.pref_branch, "public_description": experiment.public_description, "population_percent": "{0:.4f}".format(experiment.population_percent), "firefox_min_version": experiment.firefox_min_version, "firefox_max_version": experiment.firefox_max_version, "firefox_channel": experiment.firefox_channel, "client_matching": experiment.client_matching, "locales": [{ "code": "da", "name": "Danish" }], "countries": [{ "code": "CA", "name": "Canada" }], "projects": [{ "slug": project.slug }], "platforms": experiment.platforms, "windows_versions": experiment.windows_versions, "profile_age": experiment.profile_age, "objectives": experiment.objectives, "audience": experiment.audience, "features": experiment.features, "total_enrolled_clients": experiment.total_enrolled_clients, "analysis": experiment.analysis, "analysis_owner": experiment.analysis_owner.id, "survey_required": experiment.survey_required, "survey_urls": experiment.survey_urls, "survey_instructions": experiment.survey_instructions, "engineering_owner": experiment.engineering_owner, "bugzilla_id": experiment.bugzilla_id, "recipe_slug": experiment.recipe_slug, "normandy_id": experiment.normandy_id, "other_normandy_ids": experiment.other_normandy_ids, "data_science_issue_url": experiment.data_science_issue_url, "feature_bugzilla_url": experiment.feature_bugzilla_url, "risk_partner_related": experiment.risk_partner_related, "risk_brand": experiment.risk_brand, "risk_fast_shipped": experiment.risk_fast_shipped, "risk_confidential": experiment.risk_confidential, "risk_release_population": experiment.risk_release_population, "risk_revenue": experiment.risk_revenue, "risk_data_category": experiment.risk_data_category, "risk_external_team_impact": experiment.risk_external_team_impact, "risk_telemetry_data": experiment.risk_telemetry_data, "risk_ux": experiment.risk_ux, "risk_security": experiment.risk_security, "risk_revision": experiment.risk_revision, "risk_technical": experiment.risk_technical, "risk_technical_description": risk_tech_description, "risks": experiment.risks, "testing": experiment.testing, "test_builds": experiment.test_builds, "qa_status": experiment.qa_status, "review_science": experiment.review_science, "review_engineering": experiment.review_engineering, "review_qa_requested": experiment.review_qa_requested, "review_intent_to_ship": experiment.review_intent_to_ship, "review_bugzilla": experiment.review_bugzilla, "review_qa": experiment.review_qa, "review_relman": experiment.review_relman, "review_advisory": experiment.review_advisory, "review_legal": experiment.review_legal, "review_ux": experiment.review_ux, "review_security": experiment.review_security, "review_vp": experiment.review_vp, "review_data_steward": experiment.review_data_steward, "review_comms": experiment.review_comms, "review_impacted_teams": experiment.review_impacted_teams, "variants": [{ "description": variant.description, "is_control": variant.is_control, "name": variant.name, "ratio": variant.ratio, "slug": variant.slug, "value": variant.value, "addon_release_url": variant.addon_release_url, "preferences": [{ "pref_name": preference.pref_name, "pref_type": preference.pref_type, "pref_branch": preference.pref_branch, "pref_value": preference.pref_value, } for preference in variant.preferences.all()], "message_targeting": variant.message_targeting, "message_threshold": variant.message_threshold, "message_triggers": variant.message_triggers, } for variant in experiment.variants.all()], "results_url": experiment.results_url, "results_initial": experiment.results_initial, "results_lessons_learned": experiment.results_lessons_learned, "results_fail_to_launch": experiment.results_fail_to_launch, "results_recipe_errors": experiment.results_recipe_errors, "results_restarts": experiment.results_restarts, "results_low_enrollment": experiment.results_low_enrollment, "results_early_end": experiment.results_early_end, "results_no_usable_data": experiment.results_no_usable_data, "results_failures_notes": experiment.results_failures_notes, "results_changes_to_firefox": experiment.results_changes_to_firefox, "results_data_for_hypothesis": experiment.results_data_for_hypothesis, "results_confidence": experiment.results_confidence, "results_measure_impact": experiment.results_measure_impact, "results_impact_notes": experiment.results_impact_notes, "rollout_playbook": experiment.rollout_playbook, "rollout_type": experiment.rollout_type, "message_type": experiment.message_type, "message_template": experiment.message_template, } self.assertEqual(set(serializer.data.keys()), set(expected_data.keys())) self.assertEqual(serializer.data, expected_data)
def test_serializer_outputs_expected_schema(self): project1 = ProjectFactory.create(name="a") project2 = ProjectFactory.create(name="b") parent = ExperimentFactory.create() related_experiment1 = ExperimentFactory.create(slug="a") related_experiment2 = ExperimentFactory.create(slug="b") experiment = ExperimentFactory.create( proposed_start_date=datetime.date(2020, 1, 1), parent=parent, projects=[project1, project2], ) experiment.related_to.add(related_experiment1, related_experiment2) serializer = ExperimentCSVSerializer(experiment) self.assertDictEqual( serializer.data, { "name": experiment.name, "type": experiment.type, "status": experiment.status, "experiment_url": experiment.experiment_url, "public_description": experiment.public_description, "owner": experiment.owner.email, "analysis_owner": experiment.analysis_owner.email, "engineering_owner": experiment.engineering_owner, "short_description": experiment.short_description, "objectives": experiment.objectives, "parent": experiment.parent.experiment_url, "projects": f"{project1.name}, {project2.name}", "data_science_issue_url": experiment.data_science_issue_url, "feature_bugzilla_url": experiment.feature_bugzilla_url, "firefox_channel": experiment.firefox_channel, "normandy_slug": experiment.normandy_slug, "proposed_duration": experiment.proposed_duration, "proposed_start_date": "2020-01-01", "related_to": (f"{related_experiment1.experiment_url}, " f"{related_experiment2.experiment_url}"), "related_work": experiment.related_work, "results_initial": experiment.results_initial, "results_url": experiment.results_url, }, )
def test_experiment_status_validation_should_not_raise_for_new_exp(self): project = ProjectFactory.create() experiment = ExperimentFactory.build(project=project) experiment.status = experiment.STATUS_ACCEPTED experiment.save(validate=True)