背景:
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() } }
附件是生成的报告截图