Background Image
Table of Contents Table of Contents
Previous Page  385 / 478 Next Page
Information
Show Menu
Previous Page 385 / 478 Next Page
Page Background

If we have a look through our form tests, we’ll see that, actually, only item

is tested

explicitly. On items

and

we were lucky—they’re default features of a Django

ModelForm

, and they are actually covered by our tests for the parent

ItemForm

class.

But contract clause number

managed to slip through the net.

When doing outside-in TDD with isolated tests, you need to keep

track of each test’s implicit assumptions about the contract which the

next layer should implement, and remember to test each of those in

turn later. You could use our scratchpad for this, or create a place‐

holder test with a

self.fail

.

Fixing the Oversight

Let’s add a new test that our form should return the new saved list:

lists/tests/test_forms.py (ch19l038-1).

@patch

(

'lists.forms.List.create_new'

)

def

test_save_returns_new_list_object

(

self

,

mock_List_create_new

):

user

=

Mock

(

is_authenticated

=

lambda

:

True

)

form

=

NewListForm

(

data

=

{

'text'

:

'new item text'

})

form

.

is_valid

()

response

=

form

.

save

(

owner

=

user

)

self

.

assertEqual

(

response

,

mock_List_create_new

.

return_value

)

And, actually, this is a good example—we have an implicit contract with the

List.cre

ate_new

, we want it to return the new list object. Let’s add a placeholder test for that.

lists/tests/test_models.py (ch19l038-2).

class

ListModelTest

(

TestCase

):

[

...

]

def

test_create_returns_new_list_object

(

self

):

self

.

fail

()

So, we have one test failures that’s telling us to fix the form save:

AssertionError: None != <MagicMock name='create_new()' id='139802647565536'>

FAILED (failures=2, errors=3)

Like this:

lists/forms.py (ch19l039-1).

class

NewListForm

(

ItemForm

):

def

save

(

self

,

owner

):

if

owner

.

is_authenticated

():

return

List

.

create_new

(

first_item_text

=

self

.

cleaned_data

[

'text'

],

owner

=

owner

)

else

:

return

List

.

create_new

(

first_item_text

=

self

.

cleaned_data

[

'text'

])

That’s a start, now we should look at our placeholder test:

Thinking of Interactions Between Layers as “Contracts”

|

357