《Pragmatic Unit Testing In Java with JUnit》—单元测试之道读后感

《Pragmatic Unit Testing In Java with JUnit》
                                                                  ——单元测试之道读后感

在公司实习这两周,很充实,但也很累,累是工作方式与以前不所不同,虽然基调一样,但细节方面存在很多不同,现在跟的项目很大,很重要,技术经理拟采用更规范,更严格的开发模式,所以,测试是重点之一,这两天,把Andrew Hunt David Thomas的《Pragmatic Unit Testing In Java with JUnit》看了,然后也看了JUnit的文档,把一些关键点和好的观点摘抄下来。

Testing Practices
Martin Fowler makes this easy for you. He says, "Whenever you are tempted to type something

into a print statement or a debugger expression, write it as a test instead." At first you

will find that you have to create a new fixtures all the time, and testing will seem to slow

you down a little. Soon, however, you will begin reusing your library of fixtures and new

tests will usually be as simple as adding a method to an existing TestCase subclass.

You can always write more tests. However, you will quickly find that only a fraction of the

tests you can imagine are actually useful. What you want is to write tests that fail even

though you think they should work, or tests that succeed even though you think they should

fail. Another way to think of it is in cost/benefit terms. You want to write tests that will

pay you back with information.

Here are a couple of the times that you will receive a reasonable return on your testing

investment:

    * During Development- When you need to add new functionality to the system, write the

tests first. Then, you will be done developing when the test runs.
    * During Debugging- When someone discovers a defect in your code, first write a test

that will succeed if the code is working. Then debug until the test succeeds.

One word of caution about your tests. Once you get them running, make sure they stay

running. There is a huge difference between having your suite running and having it broken.

Ideally, you would run every test in your suite every time you change a method. Practically,

your suite will soon grow too large to run all the time. Try to optimize your setup code so

you can run all the tests. Or, at the very least, create special suites that contain all the

tests that might possibly be affected by your current development. Then, run the suite every

time you compile. And make sure you run every test at least once a day: overnight, during

lunch, during one of those long meetings….
Conclusion
This article only scratches the surface of testing. However, it focuses on a style of

testing that with a remarkably small investment will make you a faster, more productive,

more predictable, and less stressed developer.

Once you've been test infected, your attitude toward development is likely to change. Here

are some of the changes we have noticed:

There is a huge difference between tests that are all running correctly and tests that

aren't. Part of being test infected is not being able to go home if your tests aren't 100%.

If you run your suite ten or a hundred times an hour, though, you won't be able to create

enough havoc to make you late for supper.

Sometimes you just won't feel like writing tests, especially at first. Don't. However, pay

attention to how much more trouble you get into, how much more time you spend debugging, and

how much more stress you feel when you don't have tests. We have been amazed at how much

more fun programming is and how much more aggressive we are willing to be and how much less

stress we feel when we are supported by tests. The difference is dramatic enough to keep us

writing tests even when we don't feel like it.

You will be able to refactor much more aggressively once you have the tests. You won't

understand at first just how much you can do, though. Try to catch yourself saying, "Oh, I

see, I should have designed this thus and so. I can't change it now. I don't want to break

anything." When you say this, save a copy of your current code and give yourself a couple of

hours to clean up. (This part works best you can get a buddy to look over your shoulder

while you work.) Make your changes, all the while running your tests. You will be surprised

at how much ground you can cover in a couple of hours if you aren't worrying every second

about what you might be breaking.

For example, we switched from the Vector-based implementation of MoneyBag to one based on

HashTable. We were able to make the switch very quickly and confidently because we had so

many tests to rely on. If the tests all worked, we were sure we hadn't changed the answers

the system produced at all.

You will want to get the rest of your team writing tests. The best way we have found to

spread the test infection is through direct contact. The next time someone asks you for help

debugging, get them to talk about the problem in terms of a fixture and expected results.

Then say, "I'd like to write down what you just told me in a form we can use." Have them

watch while you write one little test. Run it. Fix it. Write another. Pretty soon they will

be writing their own.

So- give JUnit a try. If you make it better, please send us the changes so we can spread

them around. Our next article will double click on the JUnit framework itself. We will show

you how it is constructed, and talk a little about our philosophy of framework development.

We would like to thank Martin Fowler, as good a programmer as any analyst can ever hope to

be, for his helpful comments in spite of being subjected to early versions of JUnit.

============================================================================================
Properties of Good Tests
好的测试所具有的品质
A-TRIP

  • 自动化(Automatic)
  • 彻底的(Thorough)
  • 可重复(Repeatable)
  • 独立的(Independent)
  • 专业的(Professional)</li>

战斗口号“不要修修补补,完全重写”

============================================================================================

测试的礼貌

  • 不完整的代码
  • 不能便宜的代码
  • 代码能便宜,但是会破外已经存在的代码,比如使得已经存在的代码编译失败
  • 没有相应单元测试的代码
  • 不能通过单元测试的代码
  • 通过了自己的测试,但是导致系统其他地方的其他测试失败的代码</li>

============================================================================================
编码和评审以这样的顺序进行:
1、编写 test case 和/或测试代码
2、评审 test case 和/或测试代码
3、经评审修改 test case 和/或测试代码
4、编写能通过所有测试的产品代码
5、评审产品代码和测试代码
6、在每次评审后,修改测试代码和产品代码
============================================================================================
CORRECT边界条件

  • 一致性(conformance)——值是否符合预期的格式?
  • 有序性(Ordering)——一组值是该有序的,还是该无序的?
  • 区间性(Range)——值是否在一个合理的最大值和最小值的范围之内?
  • 引用,耦合性(Reference)——代码是否引用了一些不受代码本身直接控制的外部因素?
  • 存在性(Existence)——值是否存在(例如,非null, 非零, 包含于某个集合等)?
  • 基数性(Cardinality)——是否恰好有足够的值?
  • 时间性,绝对的或者相对的(Time)——所有事情是否都是按顺序发生的?是否在正确的时间?是否及时?
posted @ 2006-03-31 22:47  电视机9号  阅读(861)  评论(0编辑  收藏  举报