JUnit in Action, Third Edition Chapter 5 Software testing principles, Chapter 6 Test quality

learning.oreilly.com

5 Software testing principles

   5.1.3 Detecting regressions and limiting debugging

passing unit test suite confirms that your code works and gives you the confidence to modify your existing code, either for refactoring or to add and modify new features.

コードに手を加える際の自信は結局は調査工数の削減にもなるのではと思う。

 

   5.1.6 Documenting expected behavior

unit tests match the production code, they must be up to date, unlike other forms of documentation

ドキュメントとしてのテストという発想は自分の中では無かったので新しい発見。

 

6 Test quality

Test coverage can ensure some of the quality of your programming, but it is also a controversial metric. High code coverage does not tell you anything about the quality of the tests. A good programmer should be able to see beyond the pure percentage obtained by running tests.

coverage 以外でテストの品質を定量的に図る方法ないのかな?

 

     6.1.1 Introduction to test coverage

上の図はblack box tests とUnit testsのコードカバレッジを比べた図。画面からのテストだけどは実装の都合上通ることないコードが発生するのでカバレッジ100%は難しい。だからUnit Testが必要。

   

     6.2.1 Understanding that public APIs are contracts

Imagine a public method that takes a distance as a double parameter and uses a black-box test to verify a computation. At some point, the meaning of the parameter changes from miles to kilometers. Your code still compiles, but the runtime breaks. Without a unit test to fail and tell you what is wrong, you may spend a lot of time debugging and talking to angry customers.

この本ではこのような問題の対策としてUnit testを推奨しているが、Domain Driven Developmentの本にはprimitive type でもCustom Classにwrapして引数として渡すべきとある。このケースだと DistanceInKilometer , DistanceInMiles みたいなクラスにdoubleを格納してあげるとよさそう。

 

           6.2.2 Reducing dependencies

To write testable code, you should reduce dependencies as much as possible. If your classes depend on many other classes that need to be instantiated and set up with some state, your tests will be very complicated

この問題に対するSolution

before

class Vehicle {
 
   Driver d = new Driver();
   boolean hasDriver = true;
 
   private void setHasDriver(boolean hasDriver) {
      this.hasDriver = hasDriver;
   }
}

after

class Vehicle {
 
   Driver d;
   boolean hasDriver = true;
 
   Vehicle(Driver d) {
      this.d = d;
   }
 
   private void setHasDriver(boolean hasDriver) {
      this.hasDriver = hasDriver;
   }
}

依存はDIしてあげたほうがMockオブジェクトが作りやすくてテストがしやすい。

 

            6.2.4 Following the Law of Demeter (Principle of Least Knowledge)

The Law of Demeter, or Principle of Least Knowledge, states that one class should know only as much as it needs to know.

メソッドの引数に渡す情報は最小限にしてあげるとテストが書きやすい。