Example #1
0
def push_experiment_to_kinto(experiment_id):
    metrics.incr("push_experiment_to_kinto.started")

    experiment = Experiment.objects.get(id=experiment_id)
    if not ExperimentBucketRange.objects.filter(
            experiment=experiment).exists():
        ExperimentBucketNamespace.request_namespace_buckets(
            experiment.recipe_slug,
            experiment,
            NIMBUS_DATA["ExperimentDesignPresets"]["empty_aa"]["preset"]
            ["arguments"]["bucketConfig"]["count"],
        )

    data = ExperimentRapidRecipeSerializer(experiment).data

    logger.info(f"Pushing {experiment} to Kinto")

    try:
        client.push_to_kinto(data)

        experimenter_kinto_user, _ = get_user_model().objects.get_or_create(
            email=settings.KINTO_DEFAULT_CHANGELOG_USER,
            username=settings.KINTO_DEFAULT_CHANGELOG_USER,
        )

        changed_values = {
            "recipe": {
                "new_value": data,
                "old_value": None,
                "display_name": "Recipe"
            }
        }
        ExperimentChangeLog.objects.create(
            experiment=experiment,
            old_status=experiment.status,
            new_status=experiment.status,
            message="Recipe Sent to Kinto",
            changed_values=changed_values,
            changed_by=experimenter_kinto_user,
        )

        logger.info(f"{experiment} pushed to Kinto")
        metrics.incr("push_experiment_to_kinto.completed")
    except Exception as e:
        metrics.incr("push_experiment_to_kinto.failed")
        logger.info(f"Pushing {experiment} to Kinto failed: {e}")
        raise e
Example #2
0
    def test_get_rapid_experiment_recipe_returns_recipe_info_for_experiment(
            self):
        experiment = ExperimentRapidFactory.create_with_status(
            Experiment.STATUS_LIVE)

        response = self.client.get(
            reverse(
                "experiment-rapid-recipe-detail",
                kwargs={"recipe_slug": experiment.recipe_slug},
            ), )

        self.assertEqual(response.status_code, 200)
        json_data = json.loads(response.content)
        serialized_experiment = ExperimentRapidRecipeSerializer(
            experiment).data

        self.maxDiff = None
        self.assertEqual(serialized_experiment, json_data)
Example #3
0
    def test_push_experiment_to_kinto_sends_experiment_data(self):
        tasks.push_experiment_to_kinto(self.experiment.id)

        data = ExperimentRapidRecipeSerializer(self.experiment).data

        self.assertTrue(
            ExperimentBucketRange.objects.filter(
                experiment=self.experiment).exists())

        bucketConfig = data["arguments"]["bucketConfig"].copy()
        bucketConfig.pop("start")
        bucketConfig.pop("namespace")

        designPreset = NIMBUS_DATA["ExperimentDesignPresets"]["empty_aa"][
            "preset"]["arguments"]["bucketConfig"]

        self.assertEqual(bucketConfig, designPreset)

        self.mock_kinto_client.create_record.assert_called_with(
            data=data,
            collection=settings.KINTO_COLLECTION,
            bucket=settings.KINTO_BUCKET,
            if_not_exists=True,
        )

        changed_values = {
            "recipe": {
                "new_value": data,
                "old_value": None,
                "display_name": "Recipe"
            }
        }

        self.assertTrue(
            ExperimentChangeLog.objects.filter(
                experiment=self.experiment,
                changed_by__email=settings.KINTO_DEFAULT_CHANGELOG_USER,
                changed_values=changed_values,
            ).exists())
Example #4
0
    def test_get_rapid_experiment_recipe_returns_recipe_info_for_experiment(
            self):
        experiment = ExperimentFactory.create_with_variants(
            status=Experiment.STATUS_LIVE,
            type=ExperimentConstants.TYPE_RAPID,
            objectives="gotta go fast",
            audience="us_only",
            features=["pinned_tabs"],
            recipe_slug="recipe-slug",
        )

        response = self.client.get(
            reverse(
                "experiment-rapid-recipe-detail",
                kwargs={"recipe_slug": experiment.recipe_slug},
            ), )

        self.assertEqual(response.status_code, 200)
        json_data = json.loads(response.content)
        serialized_experiment = ExperimentRapidRecipeSerializer(
            experiment).data

        self.maxDiff = None
        self.assertEqual(serialized_experiment, json_data)
    def test_serializer_outputs_expected_schema_for_accepted(self):
        audience = "us_only"
        features = ["pinned_tabs", "picture_in_picture"]
        experiment = ExperimentFactory.create_with_status(
            Experiment.STATUS_ACCEPTED,
            audience=audience,
            features=features,
            firefox_channel=Experiment.CHANNEL_RELEASE,
            firefox_min_version="80.0",
            proposed_start_date=None,
            proposed_duration=28,
            proposed_enrollment=7,
            rapid_type=Experiment.RAPID_AA,
            type=Experiment.TYPE_RAPID,
        )
        experiment.variants.all().delete()
        ExperimentVariantFactory.create(experiment=experiment,
                                        ratio=1,
                                        slug="control",
                                        is_control=True)
        ExperimentVariantFactory.create(experiment=experiment,
                                        ratio=1,
                                        slug="treatment",
                                        is_control=False)

        ExperimentBucketNamespace.request_namespace_buckets(
            experiment.recipe_slug, experiment, 100)

        serializer = ExperimentRapidRecipeSerializer(experiment)
        data = serializer.data

        arguments = data.pop("arguments")
        branches = arguments.pop("branches")

        self.assertDictEqual(
            data,
            {
                "id":
                experiment.recipe_slug,
                "filter_expression":
                "env.version|versionCompare('80.!') >= 0",
                "targeting":
                f'[userId, "{experiment.recipe_slug}"]'
                "|bucketSample(0, 100, 10000) "
                "&& localeLanguageCode == 'en' && region == 'US' "
                "&& browserSettings.update.channel == 'release'",
                "enabled":
                True,
            },
        )

        self.assertDictEqual(
            dict(arguments),
            {
                "userFacingName": experiment.name,
                "userFacingDescription": experiment.public_description,
                "slug": experiment.recipe_slug,
                "active": True,
                "isEnrollmentPaused": False,
                "endDate": None,
                "proposedEnrollment": experiment.proposed_enrollment,
                "features": features,
                "referenceBranch": "control",
                "startDate": None,
                "bucketConfig": {
                    "count": experiment.bucket.count,
                    "namespace": experiment.bucket.namespace.name,
                    "randomizationUnit": "userId",
                    "start": experiment.bucket.start,
                    "total": experiment.bucket.namespace.total,
                },
            },
        )
        converted_branches = [dict(branch) for branch in branches]
        self.assertEqual(
            converted_branches,
            [
                {
                    "ratio": 1,
                    "slug": "treatment",
                    "value": None
                },
                {
                    "ratio": 1,
                    "slug": "control",
                    "value": None
                },
            ],
        )