Category: Technology

  • PowerShell TDD with PSUnit: some usage examples

    I discussed setting up PSUnit for unit testing PowerShell before. This is a quick followup for my own record and consumption in the future. I will update this post as I find more interesting things to record. 1. Put PowerShell functions in one file such as myBaseFunctions.ps1; 2. Create a test directory and under that […]

  • 关于软件测试:单元测试

    上博我写了测试的重要性。现在我来谈谈软件开发最基本的测试:单元测试,unit testing。 单元测试主要用来检测某class,function,method的正确性。我想绝大多数工程师在编程时都会做各种各样的单元测试。但直到约上世纪末和本世纪初,系统性、自动化的单元测试机制才被真正地建立起来注,见下。说到这里,我们必须提到Kent Beck和Erich Gamma。 Kent Beck在90年代末用Smalltalk编程,在那段时期他写出SUnit,是用Smalltalk写出的给Smalltalk程序做单元测试的架构。在此基础之上,他和Erich Gamma携手创建了JUnit。JUnit是用Java写成的用来做Java单元测试的架构。从JUnit开始,统称为xUnit的测试架构以燎原之势传入到其它语言:Python(unittest),PHP(PHPUnit),NUnit(.Net语言如C#,VB.net)等。 xUnit的架构和基本思路实际上很简单:Arrange-Act-Assert: 1.把输入值和期望值安排好,必要时可以装逼(mock)。mock是当你的单元测试需要大、笨重、或复杂的外部资源支持时(如数据库,其它复杂API等等),你可以用个假模子mock来代替。这一步是Arrange,设定期望值; 2.调动要被测试的function/method/class,得到实际值,这是Act; 3.比较期望值和实际值,报出测试结果,这是Assert. 或许你会说,这有啥大不了的,我编程时所做的随机测试就是这么做的吗。没错,但像xUnit这样的测试机制提供了自动化、可重复性和方便性等特点。 1.自动化 良好的xUnit测试机制有所谓的test harness,即各种脚手架、工具等配套的捆绑机制。在按xUnit规范写出测试案例后,可以很方便地用该捆绑机制轻松调用全部或部分测试案例,不用笨手笨脚地做手动调节; 2.即时性 和上文紧密相关的是xUnit带来的即时性。在写出一个测试案例后,你可以很方便得用copy/paste/adjust来写出更多其它测试案例。因为有自动化机制,运行这些案例会很方便快捷,成功与否,结果立现。这样你就可以在思路、信息还停留在脑海之时,趁热打铁,迅速、有效地解决这个问题。顺便说一句,英语中也有这一俚语:strike while the iron is hot。不知该成语是否是翻译、借用来(中英或英中),我感觉自发生成的可能性大些。 单元测试是你的安全网。随着你单元测试的增多,你的安全网就变得越来越密集,漏网之鱼就会越来越少。测试给你的软件质量提供了足够的保障。 如果说我们对单元测试的重要性和自动化有了共识,我有以下想法和你共勉,让我们一起来学习和提高。弄好测试,如俗谚所说,磨刀不费砍柴工,会大大提高你的功力! 1.搜索出并安装适合你编程语言的xUnit测试框架。比方说你写PHP,那你可以用PHPUnit。如你用Python,如果是2.7以后的话,你可以用标准的unittest模块来做测试:注意要安装nose来做这个测试的harness,来方便地调用你的测试案例。像其它语言,大多数都会有xUnit,搜搜就可以找到; 2.花时间学习如何写单元测试案例和如何有效地调用单元测试。相关的tutorial,how to等应当不少; 3.在做新开发时,要给新function/method/class写单元测试。当有时间或需要修改已存在代码时,如那段代码没单元测试,逐步引进单元测试; 4.单元测试也是代码的一部分,当然要进入代码管理库; 5.用copy和paste,写出各种满足边缘参数、一般参数等各种情况下的测试案例。硬盘便宜,多存几个案例占不了多大空,注意好的文档和命名方式对案例的管理很有帮助; 6.如果在整合测试/integration test或质量检测/quality assurance甚至是生产环境中发现你的function/method/class出现问题时,请首先写出个单元测试案例来捕捉这条漏网之鱼,然后修改代码来让测试通过。这样你的安全网就会被织得更紧一些。 在完成这个修改之后,你要反思一下为什么一开始你没想到要写这个测试?为什么没有想到鱼会有这种形状和技巧来挣脱你已经编织的网?通过这种反思,你会慢慢增加你的编程洞察力、嗅觉、和敏锐。 好,先写到这里。下一篇继续。我可能会写integration testing和continuous integration testing。或者专门写一下单元测试的应用实例如Python。如有问题或评论,欢迎提出,我们一起切磋,共同前进。 注:Perl的TAP(Test Anything Protocol)值得专门提一下。早在1987年,即随Perl第一版发布,就有了自己的单元测试机制。这比SUnit(xUnit之前身)要早10年左右。之后大部分在CPAN上公布的模块都经过了Test::More的符合TAP规格的单元测试。我个人以为这是Perl作为元老级脚本语言,至今仍威风八面、历久弥新的主要原因之一。所以如果你用Perl编程,我强烈建议你掌握Test::More和相关的Test::Harness模块。

  • 关于软件测试:测试的重要性

    题记:去年12月在淘宝和奥莱利公司举办的Velocity会议上,结交了很多好朋友。当时有好多想分享的主意,回来后写了个“开源软件的参与及社区互动的一些体会和建议”系列。之后就酝酿着要写一个测试系列,因为我坚信好的测试是生产高质量软件的必要条件。后来因为有家人从各地来,再加上时间安排不当(主要是懒和自律性差)和其它方面的原因,现在才动手写这个系列。这是开头篇。 通过自己的实战经验和阅读别人经验体会,我感觉我们可以总结出在生产高质量和高可靠的软硬件产品过程中,大都会走如下流程: 尽快制出原型产品(prototype); 尽快把原型产品拿到生产环境中做检测和获得反馈; 尽快把在生产中得到的反馈数据和教训融入到下一步的故障修复和性能提升; 把改进后的产品再次尽快拿到生产环境中做检测和反馈; 循环以上步骤。 在这样的流程里,有以下几个方面特别值得注意: 1. 尽快做出原型产品并拿到实战中(或近可能类似于生产环境中)检验。 和用户互动,了解实战应用场景,检索、阅读、和了解业界同仁的文章和经验积累,搜索、阅读、分析网上网下的关于各种语言、解决方案的文档等都是很重要的过程。但把想法和了解到的信息付之与实践之前,那些理论、分析、和研究到头来只是纸上谈兵。把东西付诸与实践后,你会加深和巩固自己对已有知识的理解,碰到和解决自己和别人没有想象或碰到的问题,把学到的理论和步骤加以调整后运用到自己的环境中去。这是Kent Beck在极限编程/eXtreme Programming/XP中的一大重要、也是在实战中极端有效的一个原则。这一点和陆游在1199年写的《冬夜读书示子聿》里说得是同一个道理: 古人学问无遗力,少壮工夫老始成。 纸上得来终觉浅,绝知此事要躬行。 2. 快速的检测和反馈需要可靠、方便、和尽可能自动化的测试机制。 原型产品出来后肯定会有这样或那样的问题:有的地方需要改进和提高,有的地方需要添加新功能等等。我们在做改进和提高的同时还要做到已有功能不退化(regression bugs)。要能够实现这一目标,唯一有效的办法是建立起有效、系统、和自动化的测试脚手架。有了这种测试机制,并配有有效的源代码管理系统,我们就敢于去做代码改进和重构,就有足够的信心来保证代码的质量和可靠性。 前一段时间读Kent Beck的TDD(Test-Driven Development)书,他举了这样一个例子,我觉得挺贴切的。我们都知道用轱辘打水比从井里直接往上提省力,是打水的有效方法。假设水提到一半后你累啦或有别的情况而hold不住,你的努力就会前功尽弃。但如果你在轱辘上安装个齿轮机制来咬住你的进程而不至于让提上来的绳子后退,那你就会轻松、自信地打很多水。有效、自动化的测试机制就是你用轱辘打水的那个齿轮,它给你信心和回旋余地,让你大胆、放心地去修复、改进、重构、和添加新功能,让你有信心和实效来生产和提高产品,在保留既有功效的前提下扩大战果,打一场干脆利索、无后顾之忧(或担忧最小化)、不拖泥带水的漂亮仗! 在编程中,如果我们把每一个类/class、每一个函数/function都当作一个产品的话,根据上述“尽快做出原型产品并拿到实战中检验”的法则,我们就可以很容易地理解TDD的原理: a.我们对某类或某函数的界面有初步打算,即脑中已经设计出原型; b.在实施该类或函数之前,我们写出一个单元测试案例来在实战中应用该函数/类的原型; c.我们运行该单元测试,那么这第一个测试应当失败; d.好,接下来我们用代码来实施该函数或类的原型,直到该单元测试通过; e.我们接着写更多的测试来强化该函数/类的代码,直至新的单元测试通过; f.循环以上步骤,来搭建其它函数/类。 按照这种方式来写代码,这些单元测试就构建成咬定既有成果的齿轮和脚手架。它们给我们提供质量保证和信心,给整个产品的稳定、可靠、和高质量打下了坚实的基础。 先写到这儿,该系列的下一篇,我写一下单元测试。 后记:这些生产原型产品、实战测试和反馈、之后提高的良性循环经验过程,不仅仅可以应用到软件开发方面,个人以为在硬件、工业制造、能源和环保产品的设计和研发等很多方面也能派上用场。比方说关于节能型汽车的研发、改进和提高,关于高铁、大飞机各部件的研发和应用,关于能源产品如藻类/海藻产生能源和风能、地热能、太阳能方面的可行性研究和应用,关于很多产业向创新、高附加值型转型等等,这些对于中国和很多后发国家都有很现实的指导意义。有的东西你可以在网上、书里、和各种会议上学,有的东西别人会藏着、掖着不想让你学到,但你若不自己去应用和尝试,那永远都不会成为你自己的东西。不要自高自大,也不要妄自菲薄,一步步建立起完善的研发、测试、反馈、和提高机制,有勇气和实际行动去大胆尝试,踏踏实实地走稳每一步,那么最后领先的会是你。

  • Thinking of changing hosting company

    I purchased shared hosting service from Midphase years ago and that is where this site is hosted. It is up for renewal before 10/11. Every year during this time, for the last 2 or 3 years, I toyed with the idea of switching to a different hosting company, because the inflexibility of not having root […]

  • One example of query performance problem due to data type conversion

    In many RDBMS systems, if the value(s) passed to a query for filtering/matching is of different data type than the column data type it is comparing against, an implicit data conversion occurs. This conversion can render the index defined on said column(s) less useful or entirely useless. I encountered one such problem on SQL Server […]