安徽新华电脑专修学院_安徽电脑培训_安徽电脑培训学校_合肥电脑培训

當(dāng)前位置:首頁 > 網(wǎng)站舊欄目 > 學(xué)習(xí)園地 > 設(shè)計(jì)軟件教程 > 基于 D 2.0 編譯時(shí)反射的單元測(cè)試框架

基于 D 2.0 編譯時(shí)反射的單元測(cè)試框架
2010-01-13 22:49:47  作者:  來源:
一個(gè)模仿 Ruby Test::Unit 的 Quick & Dirty 單元測(cè)試框架,托 __traits 的福,看起來已經(jīng)有那么點(diǎn)意思了。提取行號(hào)在目前還沒法實(shí)現(xiàn),估計(jì)等 macro 出來就能解決這個(gè)問題。

SVN里的最新版在下面的鏈接處:
dotmars.googlecode.com/svn/trunk/sandbox/2.0/test.d

D2.0 代碼

 

 
  1. /**
  2. A D 2.0 unit test framework inspired by Ruby's Unit::Test
  3.  
  4. // Written in the D programming language 2.0
  5.  
  6. Authors: Wei Li (oldrev@gmail.com)
  7. License: BSD
  8. Copyright: Copyright (C) 2007 by Wei Li.
  9. */
  10.  
  11. import std.stdio;
  12.  
  13. ////////////////////////////////////////////////////////////////////////////////
  14.  
  15. struct Failure
  16. {
  17. string location;
  18. string message;
  19. string testName;
  20. }
  21.  
  22. ////////////////////////////////////////////////////////////////////////////////
  23.  
  24. struct Error
  25. {
  26. Exception exception;
  27. string testName;
  28. }
  29.  
  30. ////////////////////////////////////////////////////////////////////////////////
  31.  
  32. class TestResult
  33. {
  34. private Error[] m_errors;
  35. private Failure[] m_fails;
  36. private int m_runCount;
  37. private int m_assertionCount;
  38. private int m_testCount;
  39.  
  40. const(Error)[] errors() {
  41. return m_errors;
  42. }
  43.  
  44. const(Failure)[] failures() {
  45. return m_fails;
  46. }
  47.  
  48. void addFailure(const string loc, const string msg, const string name)
  49. {
  50. Failure f;
  51. with(f) {
  52. location = loc;
  53. message = msg;
  54. testName = name;
  55. }
  56. m_fails ~= f;
  57. }
  58.  
  59. void addError(Exception ex, const string name)
  60. {
  61. Error e;
  62. with(e) {
  63. exception = ex;
  64. testName = name;
  65. }
  66. m_errors ~= e;
  67. }
  68.  
  69. void addAssertion() {
  70. m_assertionCount++;
  71. }
  72.  
  73. void addTest() {
  74. m_testCount++;
  75. }
  76.  
  77. void addRun() {
  78. m_runCount++;
  79. }
  80.  
  81. bool hasPassed() {
  82. return m_errors.length == 0 && m_fails.length == 0;
  83. }
  84.  
  85. int errorCount() {
  86. return cast(int)m_errors.length;
  87. }
  88.  
  89. int failureCount() {
  90. return cast(int)m_fails.length;
  91. }
  92.  
  93. int runCount() {
  94. return m_runCount;
  95. }
  96.  
  97. int testCount() {
  98. return m_testCount;
  99. }
  100.  
  101. int assertionCount() {
  102. return m_assertionCount;
  103. }
  104. }
  105.  
  106.  
  107. ////////////////////////////////////////////////////////////////////////////////
  108.  
  109.  
  110. abstract class TestBase
  111. {
  112. protected this() {
  113. }
  114.  
  115. abstract void run(TestResult result);
  116.  
  117. abstract const bool isRunning();
  118. }
  119.  
  120.  
  121. ////////////////////////////////////////////////////////////////////////////////
  122.  
  123.  
  124. abstract class TestCase(Subclass) : TestBase
  125. {
  126. alias typeof(this) SelfType;
  127.  
  128. struct TestMethod
  129. {
  130. string name;
  131. void delegate() method;
  132. }
  133.  
  134. public const string name = Subclass.classinfo.name;
  135.  
  136. private TestResult m_result;
  137. private TestMethod[] m_methods;
  138. private size_t m_currentMethod;
  139. private bool m_isFailed;
  140. private bool m_running = false;
  141.  
  142. this() {
  143. }
  144.  
  145. private static const(string) ctfMakeString(T)()
  146. {
  147. string ret;
  148. foreach(str; __traits(allMembers, T)) {
  149. if(str[0..4] == "test")
  150. ret ~= `addTestMethod(TestMethod("` ~ str ~ `", &sc.` ~ str ~ `)); ` ~ "\n";
  151. }
  152. return ret;
  153. }
  154.  
  155. private void initial(const Subclass sc) {
  156. mixin(ctfMakeString!(Subclass)());
  157. }
  158.  
  159. void addTestMethod(TestMethod tm) {
  160. m_methods ~= tm;
  161. }
  162.  
  163. static Subclass createChild() {
  164. auto o = new Subclass;
  165. o.initial(o);
  166. return o;
  167. }
  168.  
  169. void setup() {}
  170.  
  171. void teardown() {}
  172.  
  173. override const bool isRunning() {
  174. return m_running;
  175. }
  176.  
  177. override void run(TestResult result)
  178. {
  179. m_result = result;
  180. m_result.addRun();
  181.  
  182. foreach(size_t i, TestMethod tm; m_methods)
  183. {
  184. m_isFailed = false;
  185. m_currentMethod = i;
  186. m_result.addTest();
  187. setup();
  188. m_running = true;
  189.  
  190. try {
  191. tm.method();
  192. }
  193. catch(Exception ex) {
  194. m_result.addError(ex, currentMethodName);
  195. }
  196. finally {
  197. m_running = false;
  198. }
  199.  
  200. teardown();
  201. }
  202. }
  203.  
  204. const string currentMethodName() {
  205. return name ~ "." ~ m_methods[m_currentMethod].name;
  206. }
  207.  
  208. private void addFailure(const string message = null)
  209. {
  210. if(!m_isFailed)
  211. {
  212. m_isFailed = true;
  213. m_result.addFailure(name, message, currentMethodName);
  214. }
  215. }
  216.  
  217. //////////////////////////// Assertion Functions ///////////////////////////
  218.  
  219. void assertTrue(bool x, const string message = null)
  220. {
  221. m_result.addAssertion();
  222. if(!x) {
  223. addFailure(message);
  224. }
  225. }
  226.  
  227. void assertNull(T)(const T value, const string message = null)
  228. {
  229. m_result.addAssertion();
  230. if(value !is null) {
  231. addFailure(message);
  232. }
  233. }
  234.  
  235. void assertNotNull(T)(const T value, const string message = null)
  236. {
  237. m_result.addAssertion();
  238. if(value is null) {
  239. addFailure(message);
  240. }
  241. }
  242.  
  243. void assertEqual(T)(const T expected, const T actual, const string message = null)
  244. {
  245. m_result.addAssertion();
  246. if(expected != actual) {
  247. addFailure(message);
  248. }
  249. }
  250.  
  251. void assertNotEqual(T)(const T expected, const T actual, const T delta, const string message = null)
  252. {
  253. m_result.addAssertion();
  254. if(expected == actual) {
  255. addFailure(message);
  256. }
  257. }
  258.  
  259. void flunk(const string message = "Flunked")
  260. {
  261. m_result.addAssertion();
  262. addFailure(message);
  263. }
  264.  
  265. }
  266.  
  267.  
  268. ////////////////////////////////////////////////////////////////////////////////
  269.  
  270. class TestSuit(Subclass, Tests...) : TestBase
  271. {
  272. alias typeof(this) SelfType;
  273.  
  274. public const string name = Subclass.classinfo.name;
  275. private TestBase[] m_tests;
  276. private bool m_running = false;
  277.  
  278. this()
  279. {
  280. m_running = false;
  281.  
  282. foreach(T; Tests)
  283. {
  284. T test = T.createChild();
  285. addTest(test);
  286. }
  287. }
  288.  
  289. static Subclass createChild() {
  290. return new Subclass;
  291. }
  292.  
  293. const(TestBase)[] tests() {
  294. return m_tests;
  295. }
  296.  
  297. void addTest(TestBase tb)
  298. in {
  299. assert(tb !is null);
  300. }
  301. body {
  302. m_tests ~= tb;
  303. }
  304.  
  305. const bool empty() {
  306. return Tests.length == 0;
  307. }
  308.  
  309. override const bool isRunning() {
  310. return m_running;
  311. }
  312.  
  313. override void run(TestResult result) {
  314. m_running = true;
  315. foreach(test; m_tests) {
  316. test.run(result);
  317. }
  318. m_running = false;
  319. }
  320. }
  321.  
  322.  
  323. static class ConsoleRunner
  324. {
  325. static void showFailures(TestResult tr)
  326. {
  327. foreach(fail; tr.failures)
  328. {
  329. writefln("Failure: %s [%s]", fail.testName, fail.location);
  330. writefln("%s", fail.message);
  331. writefln();
  332. }
  333. }
  334.  
  335. static void showErrors(TestResult tr)
  336. {
  337. foreach(err; tr.errors)
  338. {
  339. writefln("Error: s", err.testName);
  340. writefln("%s", err.exception.msg);
  341. writefln();
  342. }
  343. }
  344.  
  345. static void run(TestBase tb)
  346. {
  347. auto result = new TestResult;
  348. writefln("Started...");
  349. tb.run(result);
  350. writefln("Finished\n");
  351. showErrors(result);
  352. showFailures(result);
  353. writefln();
  354. writefln("%d tests, %d assertions, %d failures, %d errors",
  355. result.testCount, result.assertionCount, result.failureCount, result.errorCount);
  356. if(result.hasPassed)
  357. writefln("Everything is OK.");
  358. }
  359. }
  360.  
  361. ////////////////////////////////////////////////////////////////////////////////
  362.  
  363.  
  364. class MyTestCase : TestCase!(MyTestCase)
  365. {
  366. void testOne() {
  367. assertTrue(false, "A stupid assertion");
  368. assertTrue(true);
  369. assertTrue(true);
  370. throw new Exception("Exception raised");
  371. }
  372.  
  373. void testTwo() {
  374. assertTrue(true);
  375. }
  376.  
  377. void testThree() {
  378. assertTrue(true);
  379. }
  380. }
  381.  
  382. class MyTestCase2 : TestCase!(MyTestCase2)
  383. {
  384. void testOne() {
  385. assertTrue(true);
  386. }
  387.  
  388. void testTwo() {
  389. assertTrue(true);
  390. }
  391.  
  392. void testThree() {
  393. assertTrue(false, "Yet another stupid assertion");
  394. }
  395. }
  396.  
  397. class MyTestCase3 : TestCase!(MyTestCase3)
  398. {
  399. void testMethod() {
  400. assertTrue(true);
  401. }
  402. }
  403.  
  404.  
  405. class MyTestSuit1: TestSuit!(MyTestSuit1, MyTestCase)
  406. {
  407. }
  408.  
  409. class MyTestSuit2: TestSuit!(MyTestSuit2, MyTestCase2)
  410. {
  411. }
  412.  
  413. class MyTestSuit3: TestSuit!(MyTestSuit3, MyTestSuit1, MyTestSuit2, MyTestCase3)
  414. {
  415. }
  416.  
  417. void main()
  418. {
  419. auto ts = new MyTestSuit3;
  420.  
  421. ConsoleRunner.run(ts);
  422. }

 



運(yùn)行結(jié)果
 
oldrev@ubuntu:~/work/dotmars/sandbox/2.0$ dmd2 -run test.d
Started...
Finished

Error: stest.MyTestCase.testOne
Exception raised

Failure: test.MyTestCase.testOne [test.MyTestCase]
A stupid assertion

Failure: test.MyTestCase2.testThree [test.MyTestCase2]
Yet another stupid assertion


7 tests, 9 assertions, 2 failures, 1 errors


 

安徽新華電腦學(xué)校專業(yè)職業(yè)規(guī)劃師為你提供更多幫助【在線咨詢
主站蜘蛛池模板: 天猫代运营_淘宝代运营_正规电商代运营公司_武汉火蝠电商 | 微EAM - EHS安全管理系统-设备管理系统-设备全生命周期管理软件-HSE安全管理软件 | 箱包定制_广州箱包厂_双肩电脑背包_双肩旅行包_拉杆箱包_商务公文包_包包批发,深圳爱自由,礼品箱包定制,电话:400-0061-690 | 乐贝贝童装批发网-外贸童装批发厂家直销|网上品牌童装批发市场|儿童服装批发首选 | 微米环境-餐厨/厨余/果蔬垃圾处理设备厂家-大型成套设备解决方案 | 南京展览公司|南京会展制作|南京展台搭建|南京展厅设计|企业展览馆 | 河北省农林科学院石家庄果树研究所| 沈阳东鹰实业有限公司【官网】-聚氨酯清扫器-胶带输送机保护装置 | 中国(北京)国际园林绿化设备展览会| 沈阳机电一体化电热锅炉_沈阳蓄热式电锅炉_沈阳壁挂式电锅炉【沈阳远鹏电热供水设备工程安装有限公司】 | 赛车微信群二维码平台下载【找群网zhaoqun5.com】 | 泡沫混凝土垫层填充厂家,发泡混凝土垫层填充,轻质混凝土垫层填充厂家,深圳市鸿奥建材发展有限公司 | 砂金设备-淘金机械-金矿选矿设备厂家-青州冠诚重工机械有限公司 砂浆生产线_干混砂浆设备_干混砂浆生产线-苏州一工机械有限公司 | 天木生物科技有限公司-高通量自动化-细胞筛选平台 | 气相色谱仪生产厂家批发价格找上海惠分科学分析仪器有限公司 | 深圳家具网-家具展会-家具检测-家具品牌—深圳市家具行业协会官网 | 上海视研装饰工程有限公司-上海标识公司,上海标识设计 | 思沃普智能会议预约管理系统-视频会议管理-信息发布-访客管理-会议运维-会议支持-工位管理系统 | 扭力扳手_扭力扳手检定仪_数显扭力扳手_扭力测试仪_测力计_推拉力计_拉力测试仪_测试台架-上海实干实业有限公司 | 玉米加工机械_玉米加工设备_玉米深加工机械_玉米糁加工设备--滑县鑫丰粮油机械有限公司 | 鸿茗商务-杭州鸿茗商务咨询有限公司| 微EAM - EHS安全管理系统-设备管理系统-设备全生命周期管理软件-HSE安全管理软件 | 无塔供水设备_无负压供水设备_变频供水设备_净化过滤设备_加油站油罐_S/F双层油罐_开封市东方供水设备有限公司 | 万级无菌室-阳性对照室-干细胞实验室-广州沃霖实验室设备有限公司 | 型煤锅炉进煤机|型煤链条炉排 |重型板链除渣机 |丹东刮板输送机|丹东脱硫除尘器-铧洋机械 | 汽车漆品牌|家具漆代理|涂料加盟厂家|家具漆|汽车漆-邦派漆官网 汽车漆|汽车油漆|工业油漆涂料|汽车漆加盟-佛山市科涂涂料有限公司 | 腻子粉厂家_耐水腻子粉_内墙腻子粉批发_生态腻子粉_长沙美恩生态腻子粉厂家 | 液体灌装机-酱料灌装机-全自动灌装机-旋盖机-铝箔封口机-贴标机厂家-迈特威自动化设备(天津)有限公司" | 截止阀,电动,气动,手动,化工截止阀-上海申弘阀门有限公司 | 专利申请|知识产权贯标|商标提异议|国外专利申请-润平知识产权 | 徐州护栏,围栏,锌铁丝网围栏安全设施专家徐州铜山区威峰金属护栏厂 | 南山荔枝,深圳南荔农业荔枝园自销-质保优放心选购 | 深圳办公室装修_设计_实景_效果图_哪家好-公装装饰公司 | 气动法兰软密封蝶阀-电动高温通风蝶阀-气动开关球阀-川沪阀门 | 上饶环亚电脑会计培训学校--电脑学校|上饶电脑学校|上饶电脑培训|会计培训|上饶会计培训|上饶县会计培训|广丰会计培训|玉山会计培训|横峰会计培训|上饶网店培训 上进电缆(嘉兴)股份有限公司官网 - 光伏电缆|防火电缆|电力电缆|铝合金电缆专业生产厂家 | 聚合氯化铝pac-聚氯化铝-饮水级工业级聚合氯化铝-聚合氯化铝厂家价格 | 深圳蓝枫印刷_画册印刷_彩页印刷_宣传册印刷_包装盒印刷_彩盒印刷厂_不干胶印刷厂 | 种植槽系统,移动苗床,多层种植货架,潮汐苗床,物流苗床,潮汐面板,立体旋转育秧床,河北博超温室设备有限公司 | 活性炭吸附设备,UV光氧废气处理设备,破碎机专用除尘器,催化燃烧设备厂家-河北碧清环保设备有限公司 | 西安西雷脉冲功率技术有限公司-高压调制器/加速器与脉冲功率系统的研发/生产/应用推广/高压脉冲电源的应用研究/设计/生产和销售/高功率脉冲器件/材料与仪器设备的研发/生产和销售/高电压/大电流/强磁场环境的模拟及测试服务/会议会展服务/货物及进出口的业务/脉冲功率技术领域类的技术转让 | 九江东盛机械制造有限公司|