Example #1
0
 def test_valid_configuration(self):
     cleaver = Cleaver({}, FakeIdentityProvider(), SQLAlchemyBackend())
     assert isinstance(cleaver._identity, FakeIdentityProvider)
     assert isinstance(cleaver._backend, SQLAlchemyBackend)
Example #2
0
 def setUp(self):
     self.b = SQLAlchemyBackend('sqlite://')
Example #3
0
 def setUp(self):
     self.b = SQLAlchemyBackend()
Example #4
0
class TestFullStack(TestCase):

    def setUp(self):
        self.b = SQLAlchemyBackend('sqlite://')

    def tearDown(self):
        engine = self.b.Session.bind.connect()
        for table_name in Inspector.from_engine(engine).get_table_names():
            trans = engine.begin()

            # Attempt to truncate all data in the table and commit
            engine.execute('DELETE FROM %s' % table_name)
            trans.commit()
        engine.close()

    def test_full_conversion(self):

        def _track(environ):
            return [environ['cleaver'](
                'Coin',
                ('Heads', 'Heads'),
                ('Tails', 'Tails')
            )]

        def _score(environ):
            environ['cleaver'].score('Coin')
            return []

        # Simulate an HTTP GET to track, and an HTTP POST later to convert
        handler = cycle((_track, _track, _score))

        def app(environ, start_response):
            response_headers = [('Content-type', 'text/plain')]
            start_response('200 OK', response_headers)
            return next(handler)(environ)

        environ = {}
        setup_testing_defaults(environ)

        app = SplitMiddleware(
            app,
            lambda environ: 'ryan',
            self.b
        )

        # The first request returns a variant and stores it
        variant = app(environ, lambda *args: None)[0]
        assert variant in ('Heads', 'Tails')

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        started_on = self.b.all_experiments()[0].started_on
        assert isinstance(started_on, datetime)

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 1
        assert self.b.participants('Coin', variant) == 1

        # The second request returns the same cleaver variant
        assert app(environ, lambda *args: None)[0] == variant

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        assert self.b.all_experiments()[0].started_on == started_on

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 1
        assert self.b.participants('Coin', variant) == 1

        # The third request marks a conversion
        assert app(environ, lambda *args: None) == []

        assert experiment.conversions == 1
        assert self.b.conversions('Coin', variant) == 1

    def test_human_verification_required(self):

        def _track(environ):
            return [environ['cleaver'](
                'Coin',
                ('Heads', 'Heads'),
                ('Tails', 'Tails')
            )]

        def _score(environ):
            environ['cleaver'].score('Coin')
            return []

        # Simulate an HTTP GET to track, and an HTTP POST later to convert
        handler = cycle((_track, _score))

        def app(environ, start_response):
            response_headers = [('Content-type', 'text/plain')]
            start_response('200 OK', response_headers)
            return next(handler)(environ)

        environ = {}
        setup_testing_defaults(environ)

        app = SplitMiddleware(
            app,
            lambda environ: 'ryan',
            self.b,
            count_humans_only=True
        )

        # The first request returns a variant and stores it
        variant = app(environ, lambda *args: None)[0]
        assert variant in ('Heads', 'Tails')

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        started_on = self.b.all_experiments()[0].started_on
        assert isinstance(started_on, datetime)

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 0

        # The second request doesn't store the conversion
        # (because the visitor isn't verified as human)
        assert app(environ, lambda *args: None) == []

        assert experiment.conversions == 0
Example #5
0
from flask import Flask, request
from cleaver import SplitMiddleware
from cleaver.backend.db import SQLAlchemyBackend

app = Flask(__name__)
app.wsgi_app = SplitMiddleware(
    app.wsgi_app,
    lambda environ: environ['HTTP_USER_AGENT'],  # Track by browser
    SQLAlchemyBackend('sqlite:///experiment.data'))

template = """
    <form method="POST" action="/register">
        <button>%s</button>
    </form>
"""


@app.route("/")
def home():
    # Visiting / in a web browser will render a button
    return template % (request.environ['cleaver'](
        'call-to-action', ('control', 'Click Here, Dummy!'),
        ('test', 'Free Puppies!')))


@app.route("/register", methods=['POST'])
def register():
    # Submitting the form will go to /register to display a thank-you
    request.environ['cleaver'].score('call-to-action')
    return "Thanks for Signing Up!"
Example #6
0
from cleaver.reports.web import CleaverWebUI
from cleaver.backend.db import SQLAlchemyBackend

app = CleaverWebUI(SQLAlchemyBackend('sqlite:///experiment.data'))

from wsgiref import simple_server
print "Serving at 0.0.0.0:8081"
simple_server.make_server('', 8081, app).serve_forever()
Example #7
0
 def setUp(self):
     self.b = SQLAlchemyBackend('sqlite://')
Example #8
0
class TestFullStack(TestCase):
    def setUp(self):
        self.b = SQLAlchemyBackend('sqlite://')

    def tearDown(self):
        engine = self.b.Session.bind.connect()
        for table_name in Inspector.from_engine(engine).get_table_names():
            trans = engine.begin()

            # Attempt to truncate all data in the table and commit
            engine.execute('DELETE FROM %s' % table_name)
            trans.commit()
        engine.close()

    def test_full_conversion(self):
        def _track(environ):
            return [
                environ['cleaver']('Coin', ('Heads', 'Heads'),
                                   ('Tails', 'Tails'))
            ]

        def _score(environ):
            environ['cleaver'].score('Coin')
            return []

        # Simulate an HTTP GET to track, and an HTTP POST later to convert
        handler = cycle((_track, _track, _score))

        def app(environ, start_response):
            response_headers = [('Content-type', 'text/plain')]
            start_response('200 OK', response_headers)
            return next(handler)(environ)

        environ = {}
        setup_testing_defaults(environ)

        app = SplitMiddleware(app, lambda environ: 'ryan', self.b)

        # The first request returns a variant and stores it
        variant = app(environ, lambda *args: None)[0]
        assert variant in ('Heads', 'Tails')

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        started_on = self.b.all_experiments()[0].started_on
        assert isinstance(started_on, datetime)

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 1
        assert self.b.participants('Coin', variant) == 1

        # The second request returns the same cleaver variant
        assert app(environ, lambda *args: None)[0] == variant

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        assert self.b.all_experiments()[0].started_on == started_on

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 1
        assert self.b.participants('Coin', variant) == 1

        # The third request marks a conversion
        assert app(environ, lambda *args: None) == []

        assert experiment.conversions == 1
        assert self.b.conversions('Coin', variant) == 1

    def test_human_verification_required(self):
        def _track(environ):
            return [
                environ['cleaver']('Coin', ('Heads', 'Heads'),
                                   ('Tails', 'Tails'))
            ]

        def _score(environ):
            environ['cleaver'].score('Coin')
            return []

        # Simulate an HTTP GET to track, and an HTTP POST later to convert
        handler = cycle((_track, _score))

        def app(environ, start_response):
            response_headers = [('Content-type', 'text/plain')]
            start_response('200 OK', response_headers)
            return next(handler)(environ)

        environ = {}
        setup_testing_defaults(environ)

        app = SplitMiddleware(app,
                              lambda environ: 'ryan',
                              self.b,
                              count_humans_only=True)

        # The first request returns a variant and stores it
        variant = app(environ, lambda *args: None)[0]
        assert variant in ('Heads', 'Tails')

        assert len(self.b.all_experiments()) == 1
        assert self.b.all_experiments()[0].name == 'Coin'
        started_on = self.b.all_experiments()[0].started_on
        assert isinstance(started_on, datetime)

        experiment = self.b.get_experiment('Coin', ['Heads', 'Tails'])
        assert experiment.participants == 0

        # The second request doesn't store the conversion
        # (because the visitor isn't verified as human)
        assert app(environ, lambda *args: None) == []

        assert experiment.conversions == 0