測(cè)試的重要性是每個(gè)程序員都明白的, 但真正自己去做測(cè)試(Unit Test)的卻很少, 曾經(jīng)我也是其中的一員.
因?yàn)閷憘€(gè)main調(diào)用一些方法, 打印出結(jié)果或狀態(tài), 然后人工肉眼去排查, 若不是迫于無(wú)奈, 我相信沒(méi)有程序員愿意糾結(jié)于這些瑣碎的東西.
其實(shí), 測(cè)試本可以很有趣的.借助
JUnit, 我們可以將測(cè)試按不同的場(chǎng)景組織起來(lái), 在”一鍵”之后的紅綠條的反饋下, 快速解決代碼中存在的問(wèn)題. 如果你還不太了解JUnit, 請(qǐng)先去這里. 后文將以JUnit為基礎(chǔ), 以Fluent Interface(這個(gè)在國(guó)內(nèi)還比較時(shí)髦的術(shù)語(yǔ))為切入點(diǎn), 展示一下更有趣的測(cè)試.
在解釋什么是Fluent Interface之前, 請(qǐng)先看這樣一段測(cè)試代碼:
public class Calculator { public int sum(int one, int other); } public class CalculatorTest { private final Calculator calc = new Calcuator(); @Test public void 08 onePlusOne() { assertEquals(2, calc.sum(1, 1)); } } |
上述代碼是基于JUnit4編寫的, 用assertEquals來(lái)測(cè)試Calculator的sum方法對(duì)一加一計(jì)算的結(jié)果. 這種寫法很簡(jiǎn)單, 但從語(yǔ)義上并不是那么流暢, 若換種寫法, 如:
public class CalculatorTest { [...] @Test public void assertThatOnePlusOneIsEqualToTwo() { assertThat(calc.sum(1, 1)).isEqualTo(2); } } |
這樣閱讀起來(lái)是否感到更為清晰呢? 若是將語(yǔ)句中的符號(hào)換成空格:
assert that calc sum 1 and 1 is equal to 2
這幾乎就是人類的自然語(yǔ)言了(囧, 盡管是e文).
也許這個(gè)例子只是讓大家看到易讀性的優(yōu)勢(shì), 那么再看看下面這個(gè)易編寫的例子:
public interface Querier { Collection<String> findNameBy(int age); } public class OrderQuerier { private final Querier querier = [...] @Test public void findNamesWithAgeInThirty() { Collection<String> names = querier.findNameBy(30); assertEquals(2, names.size()); assertTrue(names.contains("allen")); assertTrue(names.contains("john")); } @Test public void findNamesWithAgeInThirty() { Collection<String> names = querier.findNameBy(30); assertThat(names).hasSize(2).contains("allen", "john"); } } |
怎么樣, 上面這個(gè)對(duì)比下, 后者是否能讓你感到”清爽”呢?
assertThat風(fēng)格的assert正是應(yīng)用了Fluent Interface, 使得測(cè)試的代碼流暢易讀, 編寫簡(jiǎn)單.
Fluent interface可以看作是借用了Method Chaining來(lái)實(shí)現(xiàn)的一種Internal DSL(Domain-Specific Language), 關(guān)于它這兒有更為全面的介紹.
前面展示的assertThat僅是FEST-Assert提供一組API的很小一部分, 它還支持其它的:
Primary Type
Object
Array
Iterator
Throwable
File
Map
除了FEST-Assert, 其實(shí)還有另一個(gè)在JUnit測(cè)試中被廣泛應(yīng)用的”assertThat”——hamcrest, 它使用靜態(tài)導(dǎo)入加工廠方法實(shí)現(xiàn)的Internal DSL, 同樣很有趣的, 不妨look一下.