QUnit是jQuery支持的一款JavaScript单页测试框架。简单易用。可以从QUnit的Github页面获取其代码。QUnit的使用与JUnit类似,相信有JUnit经验的开发者和测试人员可以很快上手。

开始写测试用例

  • test( name, expected, test )
    一个常规的测试用例。test里是测试用例的具体内容。
  • asyncTest( name, expected, test )
    一个异步测试用例。默认的test都是同步的。内容中必须显示地调用start(),测试才会开始。
  • expect( amount )
    用于测试代码中,表示在本测试里期待会执行amount个断言,大于或少于这个数量,测试都将失败。
  • module( name, lifecycle )
    定义一个名为name的模块。在可选参数lifecycle中,可以定义模块开始和结束的测试内容。具体见文档。
  • QUnit.init( )
    启动QUnit测试。如果测试在进行中,则会重新启动。基本不用。

QUnit支持的断言

  1. ok( state, message )
    真假断言,state为true则通过。类似于JUnit的assertTrue。
  2. equal( actual, expected, message )
    相等断言,actual和expected相等(==)则通过。类似于JUnit的assertEquals。
  3. notEqual( actual, expected, message )
    不等断言,actual和expected不相等(!=)则通过。类似于JUnit的assertNotEquals。
  4. deepEqual( actual, expected, message )
    递归相等断言,actual和expected全相等(包括其子元素都相等,适用于基本类型,数组和对象)则通过。对于基本类型,相当于strictEqual。
  5. notDeepEqual( actual, expected, message )
    递归不相等断言,actual和expected不全相等(包括其子元素都相等,适用于基本类型,数组和对象)则通过。对于基本类型,相当于notStrictEqual。
  6. strictEqual( actual, expected, message )
    全相等断言,actual和expected全相等(===)则通过。
  7. notStrictEqual( actual, expected, message )
    不全相等断言,actual和expected不全相等(===)则通过。
  8. raises( block, expected, message )
    异常断言,block中抛出异常则通过,expected为可选参数,是所期待抛出异常名的正则表达式。

把QUnit集成到现有工具

QUnit在执行的过程中会调用一系列函数,告知外界运行状况,大家可以覆盖这些函数,达到集成的目的。

  • QUnit.log({ result, actual, expected, message })
    每当断言执行结束后会调用此函数。
  • QUnit.testStart({ name })
    每当一个测试执行开始时会调用此函数。
  • QUnit.testDone({ name, failed, passed, total })
    每当一个测试执行结束后会调用此函数。
  • QUnit.moduleStart({ name })
    每当一个模块执行开始时会调用此函数。
  • QUnit.moduleDone({ name, failed, passed, total })
    每当一个模块执行结束后会调用此函数。
  • QUnit.begin()
    当QUnit开始时会调用此函数。
  • QUnit.done()
    当QUnit结束后会调用此函数。

在后面的实例中,我写了一些覆盖,打印了执行过程。相信有了这些回调函数的帮助,写一个进度条出来也不是难事。

QUnit的过滤器

  • noglobals
    如果勾选,那么如果一个测试中引入了全局变量,则测试会失败。JavaScript中引入全局变量(window的属性)是不推荐的行为。
  • notrycatch
    如果勾选,代码中的try-catch将不会生效,一旦程序中有异常发生,测试即刻终止。

QUnit的一个实例

页面输出如下:

页面全部代码如下:

[html]





QUnit example

    test markup, will be hidden



      [/html]

      今天订的货终于到齐了。折腾一下,很顺利,记录如下:
      我的目标:给Macbook装SSD,同时把原来的硬盘装在Macbook光驱位置,原来的光驱装在外置光盘盒里。

      1. 拆后盖:

      (1) 准备合适的家伙,后盖的螺丝虽然是十字的,但是比较细小,换内存换硬盘你会频繁打开它们,要保护好。
      (2) 经常用的Macbook,环境状况不好的话,里面会有超级多的灰,打开前要有心理准备。
      (3) 我把螺丝按拆下来位置摆成这样了。

      2. 拆光驱:

      (1) 到底把SSD盘装在原来的硬盘位,还是Optibay光驱位呢?建议装在Optibay位,因为Macbook硬盘位是有跌落保护的,因此在这里装机械硬盘能起到保护的效果。我这里是因为之前已经把SSD装在硬盘位,加上对这块Optibay硬盘改装盒并不太信任的缘故。
      (2) 你可能会发现大量的灰,建议好好清理干净。不建议用卫生纸直接擦,导致大量静电产生。最好用吹的。
      (3) 为了顺利拆下光驱,首先你要把盖在光驱上的那个条线连接在主板的一边向上拉起,并把右下黑色的无线模块两颗螺丝松开,向下掀起。不需要完全拆下。
      (4) 光驱一共由3个螺丝固定,左,右上,右下。

      3. 转移光驱的固定架:

      (1) 所谓光驱固定架,就是上面光驱边上突出来的那块金属,由两颗螺丝固定在光驱上。这里要拆下,转移到Optibay硬盘改装盒的相同位置上。
      (2) 建议购买Macbook专用的Optibay硬盘改装盒,不然有可能改装盒上没有这两个开孔。

      4. 把Optibay硬盘改装盒装到光驱位置

      (1) 顺序和拆的顺序相反,很简单了。

      5. 盖上后盖完成

      (1) 这里我没急着把螺丝拧回去。但还是盖上后盖再开机,这样可以不破坏电磁屏蔽。
      (2) 开机按Option有五个分区,我们成功了。

      6. 外置光驱

      (1) 我买的是一个套装,带一个USB 2.0的外置光驱盒,可以把拆出来的光驱装进去。

      全部完成之后,下图是SSD的固态盘速度测试:

      下图是装在OptiBay上的HDD硬盘速度测试:

      下图是接在外置盒里的光驱:

      找了张Mac安装盘,这是张D9双层盘,顺利读取:

      在默认情况下,10.6.4以后的Mac OS X只对苹果自家或者预置在Air等产品里的SSD硬盘开启TRIM技术。
      TRIM技术的基本原理是,当有文件被删除时,操作系统会发给SSD一个指令,使得SSD在空闲的时候清除被删除文件所占用的存储单元。如果TRIM没有开启,那么SSD会在存储单元再次被使用时,先清除内容,再执行写入。这个区别在于传统硬盘和SSD硬盘的实现方式上。对于传统硬盘来说,写一个数据块的时候,数据块是否有内容是无所谓的,既不会减慢写入速度也不会影响其寿命,而SSD则不然,从底层实现来看,写一个新块,比写一个包含内容的块要慢,而且长期会导致SSD存储单元寿命下降。因此在SSD硬盘上使用TRIM,会提升其写操作速度,及延长SSD硬盘寿命。

      具体的开启方法可见这篇博客
      我翻译之后把步骤写在这里,如何打开SSD的TRIM支持:

      1. 备份原来的IOAHCIBlockStorage:

      打开终端(Terminal),输入以下指令(可能需要输入密码):

      sudo cp /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage /IOAHCIBlockStorage.original

      这一步把系统原来的IOAHCIBlockStorage备份到了磁盘根目录/处。

      2. 开启TRIM

      sudo perl -pi -e ‘s|(\x52\x6F\x74\x61\x74\x69\x6F\x6E\x61\x6C\x00).{9}(\x00\x51)|$1\x00\x00\x00\x00\x00\x00\x00\x00\x00$2|sg’ /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage

      这一步更改了IOAHCIBlockStorage内容,打开TRIM。

      3. 重启系统

      如果一切正常,重启之后TRIM就已经被打开。

      以下是恢复步骤:
      如果你想关闭TRIM,执行以下命令:

      sudo perl -pi -e ‘s|(\x52\x6F\x74\x61\x74\x69\x6F\x6E\x61\x6C\x00).{9}(\x00\x51)|$1\x41\x50\x50\x4C\x45\x20\x53\x53\x44$2|sg’ /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage

      实在不行,你可以恢复到之前备份的IOAHCIBlockStorage:

      sudo cp /IOAHCIBlockStorage.original /System/Library/Extensions/IOAHCIFamily.kext/Contents/PlugIns/IOAHCIBlockStorage.kext/Contents/MacOS/IOAHCIBlockStorage

      开启TRIM之后,系统信息显示为:

      注意下面的“TRIM Support”已经显示为“YES”,说明TRIM已经成功开启了。

      机器的其他信息如下:

      开启前后速度对比,虽然不明显…

      开启前:

      开启后:

      silverlight-host

      用过Silverlight的兄弟都清楚,当在Visual Studio 2008中建立一个Silverlight Application Project时,首先会弹出一个提示框如上图,询问是否自动生成一个ASP.NET网站来托管这个Silverlight应用。默认会建立。一般情况下我们都会选择不建立,这样会在解决方案里少生成一个项目。
      自动生成一个ASP.NET网站来托管这个Silverlight应用的好处是,在每次Debug整个解决方案的时候,Visual Studio 2008会自动首先编译Silverlight项目,然后把编译结果,一个xap文件,自动拷贝到ASP.NET网站项目的ClientBin下,然后启动ASP.NET网站项目的默认页面,显示了最新版本的Silverlight应用。如下图所示。

      silverlight-host2

      问题是,如果你一开始没有让Visual Studio 2008建立那个网站项目,如果哪天你需要一个网站了,可能是各种原因,比如需要一个本地的Web Service等等,自己新建一个ASP.NET网站,就不能实现上面的自动拷贝xap文件了。

      解决方法比较绕。这是一个MSBuild问题,你需要Unload各个项目,然后用写字板打开ASP.NET的项目文件(csproj文件),然后在PropertyGroup中加一个SilverlightApplicationList项,如图:

      silverlight-host3

      注意相对路径,项目名称以及项目的GUID。这些东西都可以在解决方案文件(sln文件)里找到。就不详细解释了。

      silverlight-host4

      Reload项目之后Build,就会发现你的项目可以自动把xap文件拷贝到ClientBin下了。

      后记:作为一个使用Silverlight开发了无数年的工程师,这似乎是我第一次写关于Silverlight的博文。现在想想,大概是公司政策使然?我应该是个很守规矩的人。

      wave-on-iphone

      Google Wave是不是一种迅速花掉全部流量的方式呢,呵呵。
      速度是真的慢啊,输入速度更是不敢恭维,这种速度在with:public灌水是不太现实了,协同工作应该还行。
      看好Google Wave加入Google Apps大家庭!!

      with:public真的是个好地方,什么是真正的地球村呢?我想这就是了。
      Google Wave中的with:public是一个公共wave的大集合,真的是大杂烩的大杂烩,什么都有…而且中文的内容很多很多,当然比较低俗,贴美女的,啥都有,不禁令我为wave开放后在中国的未来捏把汗。对了,提到with:public,Twitter的public timeline也不错,不过明显不如Google Wave那么2.0。
      以前总是习惯于在Google Reader中定向地获取新信息,就好像填鸭一样,人家写什么,喂给你你就接着就行了,不用挪窝,打开Google Reader就行。现在在Wave上,信息渠道更加广泛了,说白了就是一片大森林,你自己出去觅食吧…

      大家都知道,野生的鸭子更好吃一些。

      yige-google-wave

      上图,今天在Google Wave上发现的好东东,在线听歌服务——亦歌,音质不错哦,在公司不能乱装东西同学可以试用一下。