Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tomek Kaczanowski - Practical Unit Testing with JUnit and Mockito - 2013.pdf
Скачиваний:
228
Добавлен:
07.03.2016
Размер:
6.59 Mб
Скачать

Chapter 4. Test Driven Development

4.2.2. GREEN - Write the Simplest Thing that Works

Now that you have a failing test, and a clear assertion message, you need to make the test pass – by writing code, of course!

The point here is not to go too far. It is to write the smallest amount of code that will satisfy the test. Concentrate on the task in hand. You have to make the bar green. That is it. Do not think (too much) about possible enhancements, do not worry about all the potential uses of your class, do not dwell on features that it would be "nice to have". Do not try to fulfil those requirements of the tests that have not yet been implemented (but which you can already envisage in your mind). The single failing test makes your current task clear: make it green, and nothing more.

Remember, there will be other tests. They will cover other requirements. And when their time comes, you will add all those cool features that are screaming out to you in your head "implement me now!". Ah, just let them scream for a while. Maybe they really will be required, maybe not. Your tests will tell.

Concentrate on the task at hand.

On the other hand, do not fall into the opposite trap. "Simple" and "silly" are not synonyms! The "simplest thing that works" should be simple, but reasonable. Concentrating on the task at hand is not an excuse for writing sloppy code.

I am not encouraging you to shut your ears to all of your experience gained from working as an architect or a designer. I am not saying that you should not think about the broader picture. What I am saying is "listen to your code". Have your own ideas, but listen to your code. It can guide your design. Listen to your tests also. They will tell you what is really important. They will not let you roam through the endless realm of exciting possibilities.

4.2.3. REFACTOR - Improve the Code

The question is, won’t adding simple features one by one make your final code look like a pile of randomly laid elements? The code will work, but will it be easy to enhance, will it be flexible, will it adhere to all OO principles (KISS4, DRY, SRP5 and others)? And this is how we arrive at the next step of the TDD rhythm: refactoring.

Once the test passes you can make some changes to your code. The safety net of tests gives you the confidence that you will not break anything as long as you "keep the bar green". Go on then, refactor! Remove duplicated code, change method names, update variables scope, move chunks from one place to another! And rerun your tests frequently. They will tell you precisely what damage, if any, your refactorings have caused.

And why is this step required? As some people say, "if it works, don’t fix it" – so why burden yourself with the task? The answer is that during the previous step (writing the least amount of code to satisfy a test) you focused on the task in hand, and the code implemented might not be clear enough. It works, but it might be a nightmare to maintain. And above and beyond this, when coding "only enough to pass the test" you were thinking only about that particular piece of code. Now is the time to look at the broader picture and refactor all the code you have, not just the few lines written a minute or so ago. Maybe there

4KISS, "Keep It Simple Stupid", see http://en.wikipedia.org/wiki/KISS_principle

5SRP, Single Responsibility Principle, see http://en.wikipedia.org/wiki/Single_responsibility_principle

45

Chapter 4. Test Driven Development

is some redundancy, maybe some functionality should be moved to a private function, maybe some variables should be renamed. Now is the time to do this.

If you had "refactored", and the tests still passed, but the application is broken now, it means that you were not really refactoring. You were just changing your code. Refactoring is moving around above a safety net of tests. It means working with code which is thoroughly tested. You are being unfair to "refactoring" when you accuse it of having broken something. You had simply done it badly (i.e. not tested well enough).

Refactoring the Tests

Should you also refactor the tests? Yes, you should! Remember, they are a valuable asset. You will be executing them, reading them and updating them often. They are the foundation upon which your code is built and, as such, should be robust and of the highest quality. The quality of your code depends strongly on your tests, so you had better have confidence that they are really, really good.

Refactoring is a way of restructuring the code without changing its functionality. In terms of tests, this means that the refactored tests exercise the same paths of code, call the same methods, use identical arguments, and verify the same assertions, as they were doing before you commenced the refactoring.

An obvious issue with test refactoring is that there are no tests for tests themselves, so you might accidentally introduce some unwanted changes instead of performing a refactor. Such a danger exists, but is not as serious as it might at first glance seem. First of all, unit tests, if written correctly, are really simple (see Section 10.2). They contain no complex logic such as might be prone to breaking down when changes are introduced. When you refactor tests you are more involved in just moving things around - e.g. moving some common functionality to set-up methods6 - than you are in working with test logic. Also, if you do something wrong, it is very probable that the green bar will turn to red, warning you immediately that something has gone wrong.

In summary, proceed with caution, but do not be afraid to refactor your tests. Make sure the number of executed tests has not changed, and if you do not feel confident with the changes introduced while refactoring, take a look at the code coverage report (see Section 11.3).

Adding Javadocs

During a refactoring phase I will also be taking care of Javadocs - both for production code and tests. This raises two issues:

1.First of all, your design is still not fixed. Is there a point in writing any documentation now, when the things may still be about to be changed?

2.Writing documentation now can interfere with the flow of thoughts you have. Your brain is already focusing on the next test to be written. Is it a good idea to interrupt this so-called "flow" and switch to a different activity?

These valid questions are reinforced by the natural aversion of developers to writing documentation. This results in postponing the act of its creation… which, of course, leads to there being no documentation at all. This seems really cool in the short term, but is deadly in the long run.

What I suggest is the following:

6See Chapter 11, Test Quality for more information on refactoring of the test code.

46

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]