예제 #1
0
    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)
예제 #2
0
    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()
예제 #3
0
 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")
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
0
    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)
예제 #7
0
    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)
        )
예제 #8
0
    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())
예제 #9
0
    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)))
예제 #10
0
    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)
예제 #11
0
    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)
예제 #12
0
    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,
        )
예제 #13
0
    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],
        }
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
0
    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,
            )
예제 #19
0
 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))
예제 #20
0
 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)
예제 #21
0
 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)
예제 #22
0
    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,
            )
예제 #24
0
    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)
예제 #25
0
    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,
            },
        )
예제 #26
0
    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)