一. 介紹
JFCUnit 是一款在 JUnit 基礎(chǔ)上針對(duì) Swing GUI 擴(kuò)展的單元測(cè)試工具。在同一個(gè)應(yīng)用程序中,我們可以通過(guò)組件發(fā)現(xiàn)方法查找到組件,模擬用戶動(dòng)作觸發(fā)組件事件來(lái)提供測(cè)試驅(qū)動(dòng),通過(guò)斷言驗(yàn)證組件狀態(tài)是否正確。
優(yōu)點(diǎn):
Ø 繼承了 JUnit ,具有 JUnit 進(jìn)行單元測(cè)試的所有優(yōu)點(diǎn);
Ø 提供了一系列 GUI 組件發(fā)現(xiàn)方法及用戶動(dòng)作模擬方法。
在讀下面的內(nèi)容之前,您可以先下載“ JFCUnit Example ”。這是一個(gè)完整的 eclipse 工程,首先運(yùn)行其中的一個(gè)例子,可以使您對(duì) JFCUnit 有一個(gè)感官上的了解。
二. JFCUnit API
說(shuō)明:此處僅是簡(jiǎn)單介紹,具體使用可以參見(jiàn)“ JFCUnit Example ”。
1. GUI 組件發(fā)現(xiàn)類
a.
通用命名組件發(fā)現(xiàn)類:
NamedComponentFinder
(java.lang.Class cls, java.lang.String name)
這個(gè)類使用最多,也最容易,但需要在我們的GUI程序中將組件命名(如
cancelBtn.setName(“cancelBtn”)
)
。
示例代碼
:
NamedComponentFindercancelBtnFinder = new NamedComponentFinder(JButton.class, "cancelBtn");
JButton cancelBtn = (JButton) cancelBtnFinder.find();
assertNotNull("cancelBtn not found!", cancelBtn);
assertEquals(true, cancelBtn.isEnabled());
b. 其它組件發(fā)現(xiàn)類:
這一些類主要是針對(duì)一些特定的 GUI 組件提供了一些特殊的查找方法。主要有:
等等。具體使用可以查找
API
文檔,在
junit.extensions.jfcunit
下的
doc
文檔中。
示例代碼
:
FrameFinder frameFinder = new FrameFinder("FrameDemo");
//
字符串為
Frame
標(biāo)題
List frames = frameFinder.findAll();
assertEquals("frames size wrong",1,frames.size());
JFrame frame = (JFrame)frames.get(0);
assertNotNull("frame is null !",frame);
2. 用戶動(dòng)作模擬類
這些類主要有:
等等。這些類的使用大同小異。在 “ JFCUnit Example ”也有詳細(xì)的使用例子。下面以表格為例:
finder.setName(
"table"
);
JTable table = (JTable)finder.find(frame, 0);
//
從
Frame
中查找到表格
assertNotNull(
"table not found !"
,table);
//
模擬雙擊單元格
JTableMouseEventDatatableEvent=
new
JTableMouseEventData(
this
,table,1,2,2);
helper
.enterClickAndLeave(tableEvent);
this
.flushAWT();
//
執(zhí)行事件派發(fā)隊(duì)列中的線程
,
保讓事件已經(jīng)被響應(yīng)。
//
模擬改變單元格的文本值
helper
.enterClickAndLeave(tableEvent);
this
.flushAWT();
helper
.sendKeyAction(
new
KeyEventData(
this
,tableEvent.getComponent(),KeyEvent.
VK_DELETE
));
helper
.sendString(
new
StringEventData(
this
,tableEvent.getComponent(),
""
));
helper
.sendString(
new
StringEventData(
this
,tableEvent.getComponent(),
"wukaichun"
));
this
.flushAWT();
//
模擬多選表格行
JTableMouseEventDatasrcEvent =
new
JTableMouseEventData(
this
,table,1,2,1);
JTableMouseEventDatasinkEvent =
new
JTableMouseEventData(
this
,table,2,2,1);
helper
.enterDragAndLeave(
new
DragEventData(
this
,srcEvent,sinkEvent));
this
.flushAWT();
三. 配置
對(duì)于實(shí)際 GUI 項(xiàng)目,往往需要按界面分別進(jìn)行測(cè)試。為了多個(gè)測(cè)試用例共用測(cè)試環(huán)境(不必每次都啟動(dòng)項(xiàng)目),可以將被測(cè)工程與 JUnit 一起啟動(dòng)。而后在 JUnit 的 swingUI 中選取用例執(zhí)行。
如:
package
person.jfcunit.test;
import
junit.swingui.TestRunner;
public
class
MainTest {
public
static
void
main(String[] args) {
LoginScreen.main(
new
String[]{});
//
啟動(dòng)被測(cè)
GUI
程序
TestRunner.main(
new
String[]{});
//
啟動(dòng)
JUnit
}
}
注意:
3.
啟動(dòng)配置中除主函數(shù)變?yōu)?/span>
MainTest
外,其它配置與被測(cè)工程一樣;
4.
如果使用
JUnit swingui
測(cè)試界面,為了保證所有的組件都為同一加載器加載,需要將被測(cè)類改為默認(rèn)加載器加載。
a.
找到文件
excluded.properties
,在
junit.jar
的
junit.runner
下;
b.
修改
excluded.properties
,將被測(cè)試類添加到
excluded
中,如下:
#
# The list of excluded package paths for the TestCaseClassLoader
#
excluded.0=sun.*
excluded.1=com.sun.*
excluded.2=org.omg.*
excluded.3=javax.*
excluded.4=sunw.*
excluded.5=java.*
excluded.6=org.w
excluded.7=org.xml.sax.*
excluded.8=net.jini.*
excluded.9=org.apache.commons.logging.*
excluded.9=person.*
在這里列出的包將不使用
TestCaseClassLoader
加載,而是由默認(rèn)加載器加載。如最后一行“
excluded.9=person.*
”,我們將
person
包中的類排除在
TestCaseClassLoader
加載之外。
這個(gè)時(shí)候,運(yùn)行 MainTest ,您就可以對(duì)您的項(xiàng)目進(jìn)行測(cè)試了。
四. 結(jié)束語(yǔ)
寫這篇文章的啟示是對(duì)當(dāng)前公司的 GUI 網(wǎng)管進(jìn)行單元測(cè)試時(shí)的總結(jié)。 JFCUnit 有一定的局限性,它只能針對(duì)于擴(kuò)展了 Component 的 GUI 組件進(jìn)行測(cè)試。對(duì)于 ilog 這類直接由 Object 繼承來(lái)的 GUI 則需要使用者自己擴(kuò)展。但其簡(jiǎn)單和易用性應(yīng)該能滿足大多數(shù)實(shí)際項(xiàng)目的了。
在這里共享出來(lái),希望對(duì)使用 Swing 的同仁能有點(diǎn)幫助。文章中有不明白或不正確之處,請(qǐng)不吝賜教。謝謝! Email:wukeichun@163.com 。
五. 參考資料
JFCUnit
測(cè)試
GUI
的一個(gè)實(shí)例(配置篇)
可以了解在
eclipse
下
JFCUnit
的安裝及配置。
自作聰明的
junit.swingui.TestRunner
其中解釋了使用
swing ui
界面時(shí)的類加載器問(wèn)題,值得一看。