Upload
william-weaver
View
45
Download
0
Embed Size (px)
Citation preview
Testing
Will Weaver
What I Mean by Testing?
• Automatic and repeatable checking that code written works as expected.
• Correct result
• Correct side effects
• Speedy enough
• Writing tests prior to writing code
Why Test?
• Reduce regression bugs
• Increase code quality
• Better design
• Find problems early
• Helps you know when you are done coding
Levels of Testing
• Unit
• Integration
• System / End-to-End
• Acceptance
Unit Testing
• Testing small units
• Test all cases / scenarios
• Mock / Patch external calls
Unit Test Example
1 # transaction.py 2 class Transaction(object): 3 4 def __init__(self, action, amount): 5 self.action = action 6 self.amount = amount 7 8 9 # bank_account.py10 class BankAccount(object):11 12 def __init__(self, initial_balance=0):13 self.balance = initial_balance14 self.transactions = [Transaction('initial', initial_balance)]
Unit Test Example (cont'd)17 # test_bank_account.py
18 class DescribeBankAccount(BaseTestCase):19 20 # Arrange21 @classmethod22 def configure(cls):23 cls.init_balance = 10.024 cls.transaction = cls.create_patch('bank_account.Transaction')25 26 # Act27 @classmethod28 def execute(cls):29 cls.bank_account = BankAccount(cls.init_balance)30 31 # Assert32 def should_have_balance(self):33 self.assertEqual(self.bank_account.balance, self.init_balance)34 35 def should_create_transaction(self):36 self.transaction.assert_called_once_with('initial', self.init_balance)37 38 def should_have_transactions(self):39 self.assertEqual(40 self.bank_account.transactions, [self.transaction.return_value])
Integration Testing
• Test interaction with dependencies / external calls
• Not as detailed as unit tests - no need to test every scenario
• Minimal mocking / patching
Integration Test Example
17 # test_bank_account.py18 class DescribeBankAccount(BaseTestCase):19 20 # Arrange21 @classmethod22 def configure(cls):23 cls.init_balance = 10.024 25 # Act26 @classmethod27 def execute(cls):28 cls.bank_account = BankAccount(cls.init_balance)29 30 # Assert31 def should_have_transactions(self):32 self.assertEqual(33 self.bank_account.transactions,34 [Transaction('initial', self.init_balance)],35 )
System / End-to-End Testing
• Test public endpoints
• Use full stack
• No mocking / patching
• Minimal to no inspecting of underlying side effects - only results of calls
• Run in a staging environment
System Test Example 1 # transaction.py 2 class Transaction(object): 3 4 def __init__(self, action, amount): 5 self.action = action 6 self.amount = amount 7 8 9 # bank_account.py10 class BankAccount(object):11 12 def __init__(self, initial_balance=0):13 self._balance = initial_balance14 self._transactions = [Transaction('initial', initial_balance)]15 16 def deposit(self, amount):17 self._balance += amount18 self._transactions.append(Transaction('deposit', amount))19 20 def withdraw(self, amount):21 self._balance -= amount22 self._transactions.append(Transaction('withdrawal', amount))23 24 def get_transactions(self):25 return self._transactions
System Test Example (cont’d)
28 # test_bank_account.py29 class WhenDepositingToBankAccount(BaseTestCase):30 31 # Arrange32 @classmethod33 def configure(cls):34 cls.bank_account = BankAccount(100.0)35 36 # Act37 @classmethod38 def execute(cls):39 cls.bank_account.deposit(20.0)40 cls.bank_account.deposit(25.0)41 cls.bank_account.withdrawal(10.0)42 cls.bank_account.withdrawal(5.0)43 cls.transactions = cls.bank_account.get_transactions()44 45 # Assert46 def should_have_transactions(self):47 self.assertEqual(len(self.transactions), 5)
Acceptance Testing
• Fulfill user stories
• Can be written and/or manual
• Could be written by someone other than developer - stakeholder
• Full stack
• Run against staging environment
Acceptance Testing Frameworks
• https://pypi.python.org/pypi/behave
• http://robotframework.org/
• A few more found here:https://wiki.python.org/moin/PythonTestingToolsTaxonomy#Acceptance.2FBusiness_Logic_Testing_Tools