groovy用AntBuidler写unit test之并导出自定义report
?
?
背景:
?
build.xml现在我一般用build.groovy代替了,自己用AntBuilder做***,
?
1. 想在build.groovy里运行一个unit-test-suit(groovy文件),于是代码如下:
def ant = new AntBuilder()ant.path id: 'classpath', {pathelement path: bin_dirpathelement path: gy_dirpathelement path: config_dir_appfileset 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.TestResultimport junit.framework.TestSuiteimport junit.textui.TestRunnerimport util.WebxHtmlTestListener// src/test directory pathString 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 formatdef 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 utilimport junit.framework.*/*** TIPS: test methods with same name exception*/class WebxHtmlTestListener implements TestListener{// base dir pathString dirRoot// save all test result ( failure or error )Map results = [:]// test method namesList tests = []int stackNumLimit = 10public WebxHtmlTestListener(String dirRoot){this.dirRoot = dirRootTpl.init("${dirRoot}/tpl/", 'utf-8')}void out(Map params, String tpl, String outputPath){// blueprint css file path refer to target fileparams.dir = '../tpl'// target fileFile f = new File("${dirRoot}/output/${outputPath}.html")Tpl.out(params, tpl, f.newPrintWriter())}// generate index.html / navigation.html / summury.htmlvoid 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() > 0if(results.fail)test.hasFail = results.fail.grep{it.name == test.name}.size() > 0}def params = [:]params.title = titleparams.tests = testLlparams.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 = testNameout(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.stackTraceList 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.stackTraceList 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 utilimport 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()}}?
附件是生成的报告截图