You are currently browsing the Test Me posts tagged: tdd


Developer Testing, Not Necessarily TDD… Revisited

In a previous article, I said

Test-Driven Development is a possible development workflow that incorporates Developer Testing, but Developer Testing does not necessarily only exist in Test-Driven Development (TDD).

Later I pulled together this graphic

I could equate all of the steps between TDD and Waterfall, but would gloss over the design phase. Then, one day, someone tweeted about TDD being a design process, and they were right.

The design step is missing because TDD in its entirety is a design process. Testing is a step in this process. TDD is not a process for testing. TDD is a process for designing.

That said, it is still valuable to practice Developer Testing no matter how you design, iterate, program, or whatever to achieve the desired end product.

Developer Testing, Not Necessarily TDD

During most of my tenure at Google, I taught the Developer Testing course to nearly all the engineering nooglers in the NYC office, and as well as some other east coast offices and engineers visiting from Australia.

At Etsy, I spend a fair amount of time actually thinking about developer testing in addition to developer happiness and ways to increase developer throughput.

Test-Driven Development is a possible development workflow that incorporates Developer Testing, but Developer Testing does not necessarily only exist in Test-Driven Development (TDD).

TDD is a development style with a development cycle:

  1. Add a tests for the new functionality
  2. Run all tests and see that the new tests FAIL
  3. Implement the new functionality
  4. Run all tests and see that the new tests PASS
  5. Refactor code
  6. Repeat

Thinking about it, it’s kind of like a re-wording for the Waterfall Development Model

But I don’t think that is the issue.

Recently someone asked me about TDD, and I spoke of my hesitancy towards the idea. I told him that the whole notion of having to test first was too harsh.

He, being a believer in TDD being the way to go, was skeptical that relaxing the test first constraint would be a bad thing. But the reality is, those who can test first and work well with test first will test first no matter what, but those who cannot test first because they are overwhelmed, inexperienced, or just plan do not think that way, they will likely not test or not produce.

So he took it further, and tried to argue about inside-out versus outside-in. The notion being that if you code the implementation first and then the test (inside-out) then you will code the implementation the easiest way possible for you and the test will be difficult because it is playing second fiddle. If you code the test first and the implementation second (outside-in) then you will implement the tests against an easy to use interface, and the implementation will be written to fulfill the easy to use interface.

I honestly do see the point on inside-out versus outside-in, but you can achieve the simple to use interfaces while testing second. You just have to remember one thing:

Tests should always be treated like every other consumer of the subject under test.

In short for now, that means that if you find yourself doing something tricky in your test to work around the interface of the the subject under test (SUT), you should fix the interface of the SUT and not do something tricky in your test. Your test is a consumer just like any other object that consumes the SUT in your production code, and if it is difficult to consume it in a test, then it will be difficult to consume it in production.

Getting back to the real point at hand, Developer Testing versus TDD. It is really important that as a developer you practice some sort of developer testing.

It could be manually testing your code, but if you manually test just remember that you should write down your manual tests. Writing out the tests is a good form of communication. It will allow other developers to know what they should be testing for when they begin to play in that area of the code.

It could be an automated functional test, which is like writing down a manual test case only better because it is executable. The only warning on these is that they have many points of failure. If you decide to incorporate these into a continuous deploy environment, you will want to consider either running them as probers or alerts through something like nagios, and not as red/green tests.

It could be xUnit tests, which can be either integration tests or unit tests. Integration tests give piece of mind that the actual implementations of collaborating object work together, and unit tests allow for small, fast, nimble, deterministic tests that ensure that the logic in the individual functions are correct while testing against the interface of the collaborators. Integration tests should generally be treated with the same care as automated functional tests, as discussed above. Unit tests are great for being red/green tests in a deployment pipeline.

We could dive into more about all these ways of testing, but the main point being: as a developer it is important that you test. If you write code, throw the code over the proverbial wall, wait for a response from a tester, fix, and repeat you will waste a lot of time. You will really be doing Waterfall Development. The other thing you will lose is the opportunity to communicate what you have accomplished and how you interpreted the requirements. You will miss out on executable documentation, whether by human (manual) or machine (automated).

Do a favor for yourself and all your peers, subscribe to developer testing. There are many ways to do it.

PHPNW11

Slides for my talk “Are Your Tests Really Helping You?” are now available on Slide Share.

As presented at PHPNW11 in Manchester, UK.

PHPUnit Coding Standard: https://github.com/elblinkin/PHPUnit-CodeSniffer
(P.S. I owe tons of documentation and a few “removal of assumptions”)

BTW: #PHPNW11ROCKS

When to Write Your Own Mocks

Last post I mentioned that there is a time and a place when you could consider writing a mock by hand.

It is my humble opinion, that there is only one situation that warrants handwritten mocks: Prototyping.

What do I mean by prototyping?
When you write an application, or even add a feature to an existing application, it’s always comforting to be able to start the “whole stack” and perform exploratory testing, as a developer. I mean, you. The person writing the code, starting the “whole stack”, and using the application, or new feature, in your developer environment. This is your chance to try out whether or not the application, or feature, will come up and be usable enough. Any realistic resource on test driven development (TDD) will acknowledge that there is a prototyping phase, at the beginning of a new project.

Now why am I sticking “whole stack” in quotes?
… to annoy you. No, just kidding.

In your application stack, there is almost always some external dependency, service, that you did not write. Often times, at least one of those is either a pain or too expensive for you to have locally. Expensive could be pure cost in money, as in your company can’t afford or won’t pay for more licenses, or it could be that your developer environment just cannot handle the load of the dependency. The dependency could also be a third-party service that you cannot access from your developer machine because of firewall restrictions, or again, someone is too cheap to pay for the extra access. The short of it: It’s not always possible to test end-to-end in the development environment.

So how do handwritten mocks help with this?
Basically, there should be an implementation of the external dependency’s interface that is an in-memory instance. It can either provide fixed values, values from a config, or actually mock the behavior of the external dependency. Ideally, such an implementation would be provided by the implementor of the actual dependency since they should know best how the actual dependency should behave, but not all providers are so kind. If this is the case, then writing your mock is not necessarily a terrible idea even though it defies the rule: Only mock your own objects.

So now can I test my mock?
Last post I mentioned that testing your mocks could indicate that you are doing something wrong, or even many things wrong. If you write a mock for prototyping, remember to include it with your source code, and not your test code. Source code should have tests when possible, and test code should be so simple that it never needs test code. This way you can maintain this rule: Never include something defined in test code in an assert.

Help! My external dependency is being hostile
Hostile Dependency is possibly one of my favorite terms. In a later post I will describe how forcing hostile dependencies to adapt will make it easy to swap out dependencies later.