在日常使用的Test Framework所產出的Test Report並不是標準的 JUnit 格式。所以這使得想要回傳Test Result到Jenkins的時侯,沒辦法把 Test Result 顯示在Jenkins的Build的結果上面。然而產生JUnit report的功能在一般的Test Framework像是nose跟py.test都有,像是nose就有一個plugins是專門在處理這個問題,或者是py.test可以直接使用py.test --junitxml=path
來產生。可惜我的工具沒有。所以只好自己弄一個了。在此記錄要如何完成這個任務。
上網 Google了一下有關JUnit XML format到底長怎樣,找到Stackoverflow這篇有討論,基本上可以解決90%的疑問。有關XML的定義可以從.xsd檔中找到,而JUnit的.xsd檔,這邊可以下載。我使用XMLPad來打開,再掛載xsd的schema檔,手動體驗一下 xml 的format,基本上最簡單的的JUnit Report大概是這樣:
<testsuites xsi:noNamespaceSchemaLocation="file:///D:/junit-4.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<testsuite name="INSTALLATION RAT">
<testcase classname="INS_RAT_0001" name="Test Case Title Sample 1" time="0.046">
<system-out></system-out>
</testcase>
<testcase classname="INS_RAT_0002" name="Test Case Title Sample 2" time="4.868">
<failure message="case failed" type="failure"/>
<system-out></system-out>
<system-err></system-err>
</testcase>
</testsuite>
</testsuites>
有關一些測試數量,成功數量,失敗數量,我都省略不寫上去,因為我發現Jenkins會自動幫我們算。再來,下面是一小段產生XML Report 的 Sample Code:
def createXUnitReport(self, testResult):
lstSuites = testResult.getTestsuiteList()
eleTestsuites = Element('testsuites')
for strSuiteName in lstSuites:
eleTestsuite = SubElement(eleTestsuites, 'testsuite', name=strSuiteName)
for strTestCaseName, dicResult in testResult._dicSuites[strSuiteName]['testcases'].items():
eleTestcase = SubElement(eleTestsuite, 'testcase', classname=strTestCaseName, name=dicResult['title'], time=self.tmstafTimeToSeconds(self._getStrTime(dicResult['elapsedTime'], "00:00:00")))
if dicResult['fails']:
SubElement(eleTestcase, 'failure', type="failure", message="case failed")
if dicResult['crashes']:
SubElement(eleTestcase, 'error', type="crash", message="case crash")
#@todo: add system-out / system-err message
result = tostring(eleTestsuites)
f = file(os.path.join(self._strDestDir, self.strJUnitXml), 'wb')
f.write(result)
f.close()
當把產生這份Report功能完成之後。我在 Jenkins 驅動遠端測試機器執行測試,跑完之後使用STAF的FS Command把Test Report收回來放在jenkins的workspace中。這樣我就可以有一個最簡單來反應Build的Test Result了。
PS:在JUnit中,Testcase 的結果 Failure 跟 Error 有何不同? Failure 是指因為 assertion 所造成的 Fail,可以當成是寫Tester預期中的Fail,代表待測物行為跟我們預期的結果不行。而Error則是Exception產成的Error,可以當成是非預期的錯誤,像是程式噴Exception或是Crash等等。