背景:
build.xml现在我一般用build.groovy代替了,自己用AntBuilder做***,
1. 想在build.groovy里运行一个unit-test-suit(groovy文件),于是代码如下:
def ant = new AntBuilder()
ant.path id: 'classpath', {
pathelement path: bin_dir
pathelement path: gy_dir
pathelement path: config_dir_app
fileset dir: lib_dir, {
include name: '*.jar'
}
}
ant.taskdef name: "groovy",
classname: "org.codehaus.groovy.ant.Groovy"
ant.groovy src: "${src_dir_test}/AppTestRun.groovy",
classpathref: "classpath", {
arg value: src_dir_test
arg value: app_name + ' Unit Test Result Report'
}
2. AppTestRun.groovy如下:
import junit.framework.TestResult
import junit.framework.TestSuite
import junit.textui.TestRunner
import util.WebxHtmlTestListener
// src/test directory path
String dirRoot = args[0]
String testTitle = args[1]
// current classloader (GroovyClassLoader instance)
def cl = this.class.classLoader
TestSuite suite = new TestSuite()
new File(dirRoot).eachFileRecurse{
if(it.name.startsWith('Test') && it.name.endsWith('.groovy')){
suite.addTestSuite(cl.parseClass(new File(it.absolutePath)))
}
}
// customized output format
def testresult = new TestResult()
def listener = new WebxHtmlTestListener(dirRoot)
testresult.addListener(listener)
suite.run(testresult)
listener.outTestResult()
listener.outFrame(testTitle, testresult)
3. WebxHtmlTestListener就是用来生成html test report的了,代码如下
package util
import junit.framework.*
/**
* TIPS: test methods with same name exception
*/
class WebxHtmlTestListener implements TestListener{
// base dir path
String dirRoot
// save all test result ( failure or error )
Map results = [:]
// test method names
List tests = []
int stackNumLimit = 10
public WebxHtmlTestListener(String dirRoot){
this.dirRoot = dirRoot
Tpl.init("${dirRoot}/tpl/", 'utf-8')
}
void out(Map params, String tpl, String outputPath){
// blueprint css file path refer to target file
params.dir = '../tpl'
// target file
File f = new File("${dirRoot}/output/${outputPath}.html")
Tpl.out(params, tpl, f.newPrintWriter())
}
// generate index.html / navigation.html / summury.html
void outFrame(String title, TestResult result){
List testLl = tests.collect{[name: it]}
testLl.each{test ->
if(results.error)
test.hasError = results.error.grep{it.name == test.name}.size() > 0
if(results.fail)
test.hasFail = results.fail.grep{it.name == test.name}.size() > 0
}
def params = [:]
params.title = title
params.tests = testLl
params.result = [
errorCount: result.errorCount(),
failureCount: result.failureCount(),
wasSuccessful: result.wasSuccessful(),
]
out(params, 'testResultNav.html', 'testResultNav')
out(params, 'testResultSum.html', 'testResultSum')
out(params, 'testResultFrame.html', 'index')
}
void outTestResult(){
tests.eachWithIndex{testName, i ->
def params = [:]
params.errors = results.error?.grep{it.name == testName}
params.fails = results.fail?.grep{it.name == testName}
if(i > 0){
params.pre = tests[i - 1]
}
if(i < tests.size() - 1){
params.nn = tests[i + 1]
}
params.title = testName
out(params, 'testResult.html', testName)
}
}
String getTestName(Test test){
String name = test.toString()
return name.substring(0, name.indexOf('('))
}
public void addError(Test test, Throwable t){
if(!results.error)
results.error = []
def stacks = t.stackTrace
List ll = stacks.collect{
[
fileName: it.fileName,
className: it.className,
methodName: it.methodName,
lineNumber: it.lineNumber,
isInMsg: it.fileName && it.fileName.contains('groovy')
]
}
results.error << [name: getTestName(test),
type: 'error',
msg: t.message,
stacks: ll[0..stackNumLimit]]
}
public void addFailure(Test test, AssertionFailedError t){
if(!results.fail)
results.fail = []
def stacks = t.stackTrace
List ll = stacks.collect{
[
fileName: it.fileName,
className: it.className,
methodName: it.methodName,
lineNumber: it.lineNumber,
isInMsg: it.fileName && it.fileName.contains('groovy')
]
}
results.fail << [name: getTestName(test),
type: 'fail',
msg: t.message,
stacks: ll[0..stackNumLimit]]
}
public void endTest(Test test){
}
public void startTest(Test test){
tests << getTestName(test)
}
}
至于Tpl,我是用smart4j做html输出的,用freemarker,groovy总报错——估计是个bug,悲剧
4.
package util
import org.lilystudio.smarty4j.*
class Tpl {
def static engine = new Engine()
static void init(String path, String charset){
engine.setTemplatePath(path)
}
static void out(Map map, String tpl, Writer writer) {
def template = engine.getTemplate(tpl)
def ctx = new Context()
ctx.putAll(map)
template.merge(ctx, writer)
writer.flush()
writer.close()
}
}
附件是生成的报告截图