Skip to content

Latest commit

 

History

History
221 lines (131 loc) · 6.29 KB

stop_mocking_start_testing.rst

File metadata and controls

221 lines (131 loc) · 6.29 KB

Stop Mocking, Start Testing by Augie Fackler and Nathaniel Manista from Google Code

Presenters: Augie Fackler and Nathaniel Manista of Google Code

PyCon 2012 presentation page: https://us.pycon.org/2012/schedule/presentation/315/

Slides: https://code.google.com/a/google.com/p/stop-mocking-start-testing/

Video: http://pyvideo.org/video/629/stop-mocking-start-testing

Video running time: 34:53

Lessons

(04:18)

  • Users are not a test infrastructure.
  • Coded tests with greater human costs than CPU costs are also not a test infrastructure.
  • A project simply cannot grow this way.

(07:59)

class Real(object):
    def EnLolCat(self, phrases, words=None, kitteh=None):
        # ...

class Fake1(object):
    def EnLolCat(self, phrases, words):
        # ...

class Fake2(object):
    def EnLolCat(self, phrases):
        # ...

(08:45)

"Mock objects tell you what you want to hear."

Tests run only against mock objects

Python doesn't check that a mock is true to what it is mocking

Developers don't either!

(09:48)

Lessons

  • Share mocks among test modules.
  • When choosing between zero and one mock, try zero!

(10:33)

If you need a mock, have exactly one well-tested mock.

(12:23)

Use full system tests to make up for gaps in unit- level coverage

(13:13)

Full system tests are not a replacement for unit-level tests!

(13:29)

Test stories with full system tests

Modern Mocking

(14:29)

A collection of...

... authoritative...

... narrow...

... isolated...

... fakes.

You don't want mocks spread out all over the place that need to be updated whenever the real object changes.

Don't mock things that don't need to be mocked - things that are cheap like simple data structures or things that are stateless or simple.

They use what they call "fakes" and don't find distinctions between doubles, stubs, mocks, etc. useful.

They don't really use declarative/fluent mocks that check that they're being called the right # of times, etc. It sounds like they have formal mock classes.

Testing Today

(17:58)

Tests are written to the interface, not the implementation

Unit tests are run against both mock and real implementations

System tests are run in continuous integration and quality assurance

Design For Love And Testing

(20:30)

  • Inject object dependencies as required construction parameters.
  • Separate state from behavior
  • Define interfaces between components.
  • Decline to write a test when there's no clear interface.

Injected dependencies

(20:38)

# Not this:
class BadView(BaseView):
    def __init__(self, database=None):
        if database is None:
            # This reads a global value set by
            # a command line flag
            database = DefaultDatabase()
        self._database = database

# This:
class GoodView(BaseView):
    def __init__(self, database):
        self._database = database

They used to have optional injected dependencies -- i.e. if you didn't provide an argument with the dependency it would choose one automatically (either hard-coded or use something from a command-line option, config file, etc.)

Separate state from behavior

(21:34)

Separate state (especially storage) from behavior -- i.e.: if a method has a part that touches object attributes and a part that doesn't; factor out the parts that don't touch the attributes into a separate "free function".

Define interfaces between components

(23:29)

Decline to write a test when there's no clear interface

(23:54)

Thank you

(24:50)

Questions

(25:21)

Someone asked about adding tests to legacy code and drawing a line in the sand.

(28:41)

I mentioned "Working Effectively with Legacy Code" by Michael Feathers for a guy who asked about adding tests to untested code.

I asked the speakers about "Tell, Don't Ask" and they were not familiar with it, so I don't think it's something that they adhere strongly to.

(30:04)

An interesting point someone made is that it is nice to be able to check that mocks adhere to interfaces, e.g..: using ABCs or zope.interface. This could probably be generalized to languages like PHP. For example, this might be an argument in favor of using formal interfaces over duck typing.

(31:40)

Q: How to decide what to unit test and what to system test?

(33:49)

Mocks vs. fakes - they treat mocks as a last resort - they don't write mocks for their own classes.