測試技巧 – 你所不知道的測試黑科技
2016-01-30 18:13:16 來源: mengyidan1988 評論:0 點擊:
技巧一:處理實例化 在我想辦法讓我的Android App通過Unit Test和Integration Test的過程中,我積累了一些小的經驗與技巧,可以成功的處理比較麻煩的代碼。展示開始: 問題代碼 我想測試這段代碼 public void readDeepLink(String path) { new DeepLinkReader() readDeepLink(path);
技巧一:處理實例化
在我想辦法讓我的Android App通過Unit Test和Integration Test的過程中,我積累了一些小的經驗與技巧,可以成功的處理比較麻煩的代碼。展示開始:
問題代碼
我想測試這段代碼
我只是想確保readDeepLink()方法執行了,但是我不想真的實例化DeepLinkReader因為這會引起網絡操作。所以怎么修改呢?
解決方法
將實例化DeepLinkReader的代碼封裝到另外一個方法中,這樣就可以用一個mock覆蓋這個方法,這就可以避免在測試時實例化DeepLinkReader而可以使用Mockito來確認mock方法的執行。
解決代碼
技巧二:第三方類庫
當你在為Anddroid App編寫單元測試時,可能經常要處理第三方類庫的API。在下面的代碼中我用Picasso加載圖片。Picasso的類庫非常簡潔,所以很好操作,但當你用其他的第三方類庫時可能就不是這樣了。所以我們怎么簡化和第三方類庫的交互而同時編寫可維護性強的代碼呢?
我們可以將對第三方類庫(這里以 Picasso 為例)的調用封裝到另一個類中,使我們可以使用API并通過Assertion進行測試。
原始代碼
在這個 loadImageFromUrl 方法中,我們希望確保我們的 Presenter 被調用了,而且當 showThumbImage 是 true 的時候加載圖片。因為我們想在單元測試中驗證這一點,所以我們不想真正加載這張圖片。
為了達到目標我們新建兩個類:ImageLoader 和 ImageLoaderImpl,第一個是用于暴露API的接口,第二個是實現了第一個接口的類,用于封裝調用第三方API的操作。
修改代碼
Unit Test
在這兩個單元測試中我們可以成功地測試了 Image Loader 的相關操作而無需關心第三方API。而且如果將來要使用其他的圖片加載類庫,也無需改變測試代碼。
技巧三:提高可讀性
可讀性是高質量測試代碼的重要指標之一,而我們有可能會因為在測試中添加了無用的信息而降低可讀性,來看個實例。
例子
我們現在要測試我們用于創建 Video Object 的URL與調用 VideoPlaybackService 中的 playCurrentVideo 方法的返回值適配。我們編寫了一個helper方法,可以傳入用于實例化 Video Object 的一些參數。但是大多數情況下我們不需要設置所有的參數,比如 duration 和 displayDate 對于這個方法的測試就不起到任何作用。也就是說,我們在測試中添加了額外的且無用的信息,使測試代碼可讀性降低。
解決方案
我們可以通過使用建造者(Builder)模式優化 Video 類,從而使額外的屬性不再是必需的。下面是視頻的URL的setter方法的未經優化的代碼。
我們可以升級這個方法,使它回傳Video對象(this)而不是返回空。讓我們看一看這可以怎樣增強測試代碼的可讀性和理解性。
使用建造者模式
這樣代碼就具有更強的可讀性和可維護性了。
本文轉自:http://blog.chengdazhi.com/
在我想辦法讓我的Android App通過Unit Test和Integration Test的過程中,我積累了一些小的經驗與技巧,可以成功的處理比較麻煩的代碼。展示開始:
問題代碼
我想測試這段代碼
public void readDeepLink(String path) { new DeepLinkReader().readDeepLink(path);}
我只是想確保readDeepLink()方法執行了,但是我不想真的實例化DeepLinkReader因為這會引起網絡操作。所以怎么修改呢?
解決方法
將實例化DeepLinkReader的代碼封裝到另外一個方法中,這樣就可以用一個mock覆蓋這個方法,這就可以避免在測試時實例化DeepLinkReader而可以使用Mockito來確認mock方法的執行。
解決代碼
//在MainPresenter.java中public void readDeepLink(String path) { getDeepLinkReader().readDeepLink(path);}DeepLinkReader getDeepLinkReader() { return new DeepLinkReader(currentData, events);}//在MainPresenterTest.java中@Mock private DeepLinkReader deepLinkReader;@Test public void shouldReadDeepLink() throws Exception { MainPresenter mainPresenter = new MainPresenter() { DeepLinkReader getDeepLinkReader() { return deepLinkReader; } }; mainPresenter.readDeepLink("washingtonpost.com"); verify(deepLinkReader).readDeepLink("washingtonpost.com"); }
技巧二:第三方類庫
當你在為Anddroid App編寫單元測試時,可能經常要處理第三方類庫的API。在下面的代碼中我用Picasso加載圖片。Picasso的類庫非常簡潔,所以很好操作,但當你用其他的第三方類庫時可能就不是這樣了。所以我們怎么簡化和第三方類庫的交互而同時編寫可維護性強的代碼呢?
Picasso.with(contextLocal) .load(book.getImageUrl()) .resize(80,108) .centerInside() .into(viewHolder.imageView)
我們可以將對第三方類庫(這里以 Picasso 為例)的調用封裝到另一個類中,使我們可以使用API并通過Assertion進行測試。
原始代碼
//MyClass.classpublic void loadImageFromUrl(String imageUrl) { presenter.setCurrentPreviewImageUrl(imageUrl); if (showThumbImage) { Picasso.with(context) .load(imageUrl) .into(thumbImageView); }}
在這個 loadImageFromUrl 方法中,我們希望確保我們的 Presenter 被調用了,而且當 showThumbImage 是 true 的時候加載圖片。因為我們想在單元測試中驗證這一點,所以我們不想真正加載這張圖片。
為了達到目標我們新建兩個類:ImageLoader 和 ImageLoaderImpl,第一個是用于暴露API的接口,第二個是實現了第一個接口的類,用于封裝調用第三方API的操作。
修改代碼
// ImageLoader interfacepublic interface ImageLoader { void loadImage(String imageUrl, ImageView imageView); }// ImageLoaderImpl classpublic class ImageLoaderImpl implements ImageLoader { // fields omitted @Override public void loadImage(String imageUrl, ImageView imageView) { Picasso.with(context).load(imageUrl).into(imageView); } }//loadImageFromUrl methodpublic void loadImageFromUrl(String imageUrl) { presenter.setCurrentPreviewImageUrl(imageUrl); if (showThumbImage) { imageLoader.loadImage(imageUrl, thumbImageView); }}
Unit Test
//MyClass@Mock private ImageLoader imageLoader; @Test public void shouldLoadImageWhenShowThumbIsTrue() throws Exception { myClass.setShowThumbImage(true); myClass.loadImageFromUrl("http://www.myimageurl.png"); verify(imageLoader).loadImage(anyString(), any(ImageView.class));}@Test public void shouldNotLoadImageWhenShowThumbIsFalse() throws Exception { myClass.setShowThumbImage(false); myClass.loadImageFromUrl("http://www.myimageurl.png"); verifyZeroInteractions(imageLoader);}
在這兩個單元測試中我們可以成功地測試了 Image Loader 的相關操作而無需關心第三方API。而且如果將來要使用其他的圖片加載類庫,也無需改變測試代碼。
技巧三:提高可讀性
可讀性是高質量測試代碼的重要指標之一,而我們有可能會因為在測試中添加了無用的信息而降低可讀性,來看個實例。
例子
我們現在要測試我們用于創建 Video Object 的URL與調用 VideoPlaybackService 中的 playCurrentVideo 方法的返回值適配。我們編寫了一個helper方法,可以傳入用于實例化 Video Object 的一些參數。但是大多數情況下我們不需要設置所有的參數,比如 duration 和 displayDate 對于這個方法的測試就不起到任何作用。也就是說,我們在測試中添加了額外的且無用的信息,使測試代碼可讀性降低。
@Testpublic void shouldReceiveCurrentUrlWhenVideoAvailable() { String url = "http://www.my_video.mp4"; String displayDate = "Jan. 08, 2016"; double duration = 0.30; playbackService.setCurrentVideo(createVideo(url, displayDate, duration)); String actualUrl = playbackService.playCurrentVideo(); assertEquals("the urls are not the same", url, actualUrl);}private Video createVideo(String url, String displayDate, double duration) { Video video = new Video(); video.setUrl(url); video.setDisplayDate(displayDate); video.setDuration(duration); return video;}
解決方案
我們可以通過使用建造者(Builder)模式優化 Video 類,從而使額外的屬性不再是必需的。下面是視頻的URL的setter方法的未經優化的代碼。
public void setUrl(String url) { this.url = url;}
我們可以升級這個方法,使它回傳Video對象(this)而不是返回空。讓我們看一看這可以怎樣增強測試代碼的可讀性和理解性。
使用建造者模式
public Video setUrl(String url) { this.url = url; return this;}@Testpublic void shouldReceiveCurrentUrlWhenVideoAvailable() { String url = "http://www.my_video.mp4"; playbackService.setCurrentVideo(new Video().setUrl(url)); String actualUrl = playbackService.playCurrentVideo(); assertEquals("the urls are not the same", url, actualUrl);}
這樣代碼就具有更強的可讀性和可維護性了。
本文轉自:http://blog.chengdazhi.com/
相關熱詞搜索:單元測試 java 軟件測試 develop 研發管理
上一篇:RedKale --一個全新Java微服務框架
下一篇:一套交互設計工具推薦
分享到:
收藏
