ruiwen@billpin.com

@ruiwen

Engineer @ BillPin

 

iOS - Aug '12
Mobile Web - Sep '12
iOS Rewrite - Dec '12
Android - Jan '13
Desktop 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