4. Types of tests
• Unit tests - testing individual software
components or modules. Tests module API,
not internals.
• Integration tests - testing of integrated
modules to verify combined functionality.
• Functional / GUI tests - testing of functionality
to make sure it works as required (also
System, End-to-End, etc.).
• Load, Stress, Performance, Usability,
Acceptance tests, etc.
5. Unit tests
• White-box tests of individual units.
• Isolate each part of the program and show that the
individual parts are correct.
• Should test functions isolated from their interaction with
other parts and from I/O.
• Substitute interacting parts with method stubs, mock
objects, and fakes.
• Separation of interface from implementation.
• Benefits
• Find problems early.
• Allow for safer refactoring.
• Simplify integration.
• Can drive the design of more modular, reusable
software.
6. def add(a, b):
return a + b
!
def test_add():
assert add(4, 5) == 9
Simple assertions
7. Assertions on errors
def divide_by_zero(a):
a / 0
!
def test_zero_division():
with pytest.raises(ZeroDivisionError) as einfo:
divide_by_zero(3)
!
assert 'exceptions.ZeroDivisionError' in str(einfo.type)
assert 'by zero' in str(einfo.value)
8. import datetime
from django.utils import timezone
!
from polls.models import Poll
!
!
class TestPollMethod(object):
def test_was_published_recently_with_future_poll(self):
"""
was_published_recently() should return False for
polls whose pub_date is in the future
"""
future_poll = Poll(pub_date=timezone.now() +
datetime.timedelta(days=30))
assert future_poll.was_published_recently() == False
9. Integration tests
• Individual modules are combined and tested as a
group.
• Verifies functional, performance, and reliability
requirements placed on larger units of the software.
• Tests communication between modules.
• May still involve mocking out certain services.
10. import datetime
from django.core.urlresolvers import reverse
from django.utils import timezone
!
from polls.models import Poll
!
@pytest.mark.django_db
class TestPollView(object):
def test_index_view_with_a_past_poll(self, client):
"""
Polls with a pub_date in the past should be displayed on
the index page.
"""
create_poll(question="Past poll.", days=-30)
response = client.get(reverse('polls:index'))
!
assert 'Past poll.' ==
response.context['latest_poll_list'][0].question
11. Functional tests
• Black-box tests of a portion of the software.
• Tests what the program does, not how it does it.
• Verifies a program against its specification and
requirements.
• Slow.
• Brittle.
16. Regression testing
"As a consequence of the introduction of new bugs, program
maintenance requires far more system testing per statement written
than any other programming. Theoretically, after each fix one must
run the entire bank of test cases previously run against the system,
to ensure that it has not been damaged in an obscure way. In
practice, such regression testing must indeed approximate this
theoretical ideal, and it is very costly."
The Mythical Man-Month, Frederick P. Brooks, Jr., 1974, 122.
17. • Can be at any level of testing.
• Test for regressions, re-emergence of old faults, as
well the emergence of new ones.
• Most easily done through use of Continuous
Integration systems.
18. Continuous Integration
• Merging working copies of code in short intervals.
• Coupled with automated running of automated tests.
• Use of dedicated build environment.
19. def add(a, b):
return a + b
!
def test_add():
assert add(4, 5) == 9
Simple assertions
20. Assertions on errors
def divide_by_zero(a):
a / 0
!
def test_zero_division():
with pytest.raises(ZeroDivisionError) as einfo:
divide_by_zero(3)
!
assert 'exceptions.ZeroDivisionError' in str(einfo.type)
assert 'by zero' in str(einfo.value)
21. Testing Django apps
import datetime
from django.utils import timezone
!
from polls.models import Poll
!
!
class TestPollMethod(object):
def test_was_published_recently_with_future_poll(self):
"""
was_published_recently() should return False for
polls whose pub_date is in the future
"""
future_poll = Poll(pub_date=timezone.now() +
datetime.timedelta(days=30))
assert future_poll.was_published_recently() == False
22. import datetime
from django.core.urlresolvers import reverse
from django.utils import timezone
!
from polls.models import Poll
!
@pytest.mark.django_db
class TestPollView(object):
def test_index_view_with_a_past_poll(self, client):
"""
Polls with a pub_date in the past should be displayed on
the index page.
"""
create_poll(question="Past poll.", days=-30)
response = client.get(reverse('polls:index'))
!
assert 'Past poll.' ==
response.context['latest_poll_list'][0].question