def test_valid_configuration(self): cleaver = Cleaver({}, FakeIdentityProvider(), SQLAlchemyBackend()) assert isinstance(cleaver._identity, FakeIdentityProvider) assert isinstance(cleaver._backend, SQLAlchemyBackend)
def setUp(self): self.b = SQLAlchemyBackend('sqlite://')
def setUp(self): self.b = SQLAlchemyBackend()
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
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!"
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()
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