ruiwen@billpin.com
@ruiwen
Engineer @ BillPin
iOS - Aug '12
Mobile Web - Sep '12
iOS Rewrite - Dec '12Android - Jan '13Desktop Web - Feb 13
Acquired BillMonk - Apr '13
Facebook Integration - May '13
Profit !!1!
the tech
Behave
**BP_SENTRY is a API key provided by the Sentry installation
# Initialise BP Sentry
bp_sentry = None
bp_sentry_dsn = os.getenv('BP_SENTRY')
if bp_sentry_dsn:
bp_sentry = SentryHandler(bp_sentry_dsn)
app.logger.addHandler(bp_sentry)
def handle_exception(*args, **kwargs):
bp_sentry.client.captureException(
exc_info=kwargs.get('exc_info'),
data=get_data_from_request(request),
extra={
'app': app,
},
)
got_request_exception.connect(handle_exception, sender=app)
# Configure logging
LOGGING = {
'version': 1,
'handlers': {
'sentry': {
'level': 'INFO',
'class': 'raven.handlers.logging.SentryHandler',
'dsn': os.getenv('BP_SENTRY')
}
},
'loggers': {
'billpin': {
'handlers': ['console', 'sentry'],
'level': 'INFO',
'propagate': True
},
'billpin.worker': {
'handlers': ['console', 'sentry'],
'level': 'INFO',
'propagate': True
}
}
}
logging.config.dictConfig(LOGGING)
BEHAVE
behave is behaviour-driven development, Python style.
behave uses tests written in a natural language style, backed up by Python code.
login.feature
Scenario: invalid login
Given backend ready
and integrated with DB
and user is logged in
and user has the wrong credentials
when user attempts login
then return HTTP 403 Forbidden
and we're done
login.py
@when("user attempts login")
def step(context):
# Make the call
context.response = context.app.post(
'/api/user/link',
data=dict(
username='validuser@example.com',
password='validpassword'
), follow_redirects=True)
Running the tests
Scenario: invalid login # test/.../link.feature:14
Given backend ready # test/.../environment.py:23
And integrated with DB # test/.../environment.py:27
And user is logged in # test/.../steps/link.py:11
And user has the wrong credentials # test/.../steps/link.py:41
When user attempts login # test/.../steps/link.py:59
Then return HTTP 403 Forbidden # test/.../steps/link.py:126
And we're done # test/.../environment.py:66
Mock
environment.py
@given("integrated with BillMonk")
def step(context):
# Default classes to patch
db_mock = "billpin.DB"
# Mock out Parse backend
dbmock_patch = patch(db_mock)
context.dbmock_patch = dbmock_patch
context.dbmock = dbmock_patch.start().return_value
login.py
@when("user logs in")
def step(context):
# Set up a valid BP User
context.dbmock.login.return_value = {
"username": "validuser@example.com",
"name": "Valid User",
"firstName": "Valid",
"lastName": "User",
"email": "validuser@example.com",
"createdAt": "2013-01-01T01:01:01.001Z"
}
# Send login request
billpin.py
def login():
db = DB()
user = db.login("validuser", "supersecretpassword")
login.py
@then("ensure we login with the right credentials")
def step(context):
context.dbmock.assert_called_once_with(
"validuser",
"supersecretpassword"
)
Next Up
ruiwen@billpin.com
QUESTIONS
BillPin - PyConSG 13
By Ruiwen Chua
BillPin - PyConSG 13
- 727