blog / source / en_posts / testing_python / tdd-bdd.rst

Diff from to

File source/en_posts/testing_python/tdd-bdd.rst

-On the internet, you could often hear TDD termin. From it's definition
-Test-Driven Development you could thought that writing unit-tests and
-TDD is the same, but it isn't.
+The most common mistake in the testing world is to mess TDD and
+(unit-) testing in general. TDD is not just unit-testing, it's much
+more. TDD is a way to formalize process of developing software into
+something that more seems like a compiler-driven development, where
+instead of compiler trying to figure out errors as you develop small
+pieces, you write tests to figure them out.
-TDD is a methodology when you first write your test, and only then
-change your code until it satisfies the test. As creators of TDD
-(probably) would say, this encourages you to write better tests, not
-to skip anything, keep design simple to test and so on.
+Robert Martin defines `3 rules of TDD
+<>`_ as
-My vision here is -- I don't use TDD, but also I don't write the whole
-code first.
+- You are not allowed to write any production code unless it is to
+  make a failing unit test pass.
+- You are not allowed to write any more of a unit test than is
+  sufficient to fail; and compilation failures are failures.
+- You are not allowed to write any more production code than is
+  sufficient to pass the one failing unit test.
-What I do is I do both things simultaneously. And the reason for this
-is that TDD is great idea that makes sense, but it's hard for me to
-design functions and classes without first prototyping them. It's much
-easier and faster to prototype with real code, not with how it will be
-used when you need to create something more complex than adding just 1
-new method simple to class.
+As you can see, if your whole team of programmers would work this way,
+your codebase would keep being stable all the time, and it would
+evolve little by little, no matter how complex the tasks are.
-So I first go and prototype function with it's parameters, and only
-then go and look how test for that would look like. Then I would go
-and implement the function. Then I review changes and see what also
-needs to be covered by tests.
+From my observations, when you work with lots of "state" or when you
+need to prototype as you develop, TDD is hard to adopt, and it's
+sometimes even becomes absurd to see how people transform TDD into
+"almost-TDD" or "better-TDD" by weaken some of TDD rules (or adding
+exceptions). I actually did that too. And now I see that in places
+like "best software practices.ppt" inside my company.
-Also I should mention that it's very good idea to first be sure that
-your test fails (write it before you implement something and make sure
-it fails), because it's often that your logic is not so easy and your
-test can really not test anything.
-So as a conclusion: I may be a bad (or have not enough experience)
-person, but I don't use TDD. Also you should go and read more about
-TDD not from here definitly, and speak to people who use it a lot (I
-hope I will get opportunity to work with real person who uses it and
-knows how to TDD in a good way).
-Also, there's a technique called "ping-pong programming" when one
-person writes a test, and another implements it. Then they
-switch. Nice idea :)
+I believe you shouldn't add any exceptions in these rules of TDD or
+try to make it "more real-world from your perspective". Programmers
+are smart enough to understand if it's not fit for they're tasks or if
+they want to add some exceptions into these rules.
-Different idea is Behaviour-Driven Development. As I've heard at some
-podcast, it was born as an idea that the big question in testing is
-not "how do I test things", but "what do I need to test", "what am I
-testing". And to focus on things that you test, instead of calling
-tests "test_foo_bar" you should call tests starting from "should"
-keyword, like "should_feed_pony()" or something, and author of BDD
-created fork of JUnit that would make this happened.
+Different idea of upgrading testing experience is `Behaviour-Driven
+<>`_. The main
+idea is that you need to keep constantly focus on what you test and
+why you should do that, as a result Dan North created a `JBehave`
+framework, which was the same as `JUnit` but with test methods called
+with prefix `should_*` instead of `test_*`. BDD has whole filosophy
+behind that, you can go and read wikipedia and other things about BDD
+(for example, frameworks that let you describe your tests as plain
 As lesson from that super-idea, I now call all my tests with prefix
 ``test_should_`` (as you have probably already saw). That really helps
-focusing on what test does.
+focusing on what test does at time of test-naming. Of course, BDD is
+not just about naming your tests, but the only visible part is prefix
+one (at my tests). I am still investigating frameworks that let you
+describe test as text, but didn't have experience with that.
+ Ping-pong programming
+As a bonus, there's a technique called "ping-pong programming" when
+one person writes a test, and another implements it. Then they
  Writing test from action to mocks
-When I write tests, I start from it's name (and focus on what it
-should do), like:
+To write tests, you start from it's name (and focus on what it should
+do), like:
 .. code-block:: python
     def test_should_sort_by_name(self):
-Then I go and write what it should actually do (call the action) with
-"``# do``" comment before that.
+Then you go and write what it should actually do (call the action)
+with "``# do``" comment before that.
 .. code-block:: python
         query.order_by.assert_called_with('-name', '-updated_at')
-And at last, if necessarily, you will add all the ``@patch`` before method.
+And at last, if necessarily, you will add all the ``@patch`` before
+method. That's an idea of building a test without a lot of thinking
+about what to start from, and moving step-by-step from smaller pieces
+to whole-picture of test.
 Let's move on to :doc:`change-the-way`.