2013-02-12 52 views
16

我们最近升级到JavaScript缩小库的较新版本。如何测试JavaScript缩小输出

经过测试团队进行大量质量保证工作后,发现我们minifier的新版本存在一个问题,它改变了代码块背后的意图和含义。

(生命的教训:除非你真的相信你需要新的版本不升级JS minifiers)

的minifier用于客户端以沉重强调DOM相关活动的JavaScript代码,几乎没有尽可能多的“商业逻辑”。

什么是由minifier升级打破了简单的例子:

function process(count) 
{ 
    var value = ""; 
    value += count; //1. Two consecutive += statements 
    value += count; 
    count++;  //2. Some other statement 
    return value; //3. Return 
} 

正确当时精缩到以下几点:

function process(n){var t="";return t+n+n,n++,t} 

虽然我们可以写一些单元测试来捕捉一些的问题潜在地,由于JavaScript在DOM交互(数据输入等)方面很重要,所以在没有用户测试(非自动化)的情况下进行彻底测试是非常困难的。我们曾想过使用像Esprima这样的JS to AST库,但考虑到可以对缩小代码进行更改的性质,它会产生太多的误报。

我们也考虑尝试编写具有代表性的测试,但这似乎是一个永无止境的任务(可能会遗漏案例)。

供参考:这是一个非常复杂的Web应用程序,包含几十万行JavaScript代码。

我们正在寻找一种测试缩小过程的方法,因为“只需再次测试一切,彻底并重复测试”。我们希望在这个过程中应用更多的严谨/科学。

理想情况下,如果我们有更好的科学测试方法,我们可以尝试使用多个minifier而不用担心每次都会以新的细微方式破坏我们的代码。

更新:

一个想法,我们必须是:

  1. 采取缩小与旧版本
  2. 美化它
  3. 缩小与新版本,
  4. 美化,并
  5. 视觉差异。

它似乎确实是一个好主意,但差异非常普遍,diff工具几乎将每一行标记为不同。

+3

您使用哪种微粉机? – Blender 2013-02-12 20:36:41

+0

我无法说明我与这个问题有多大关系。示例代码充其量是欢闹的。 – Arindam 2013-02-12 20:36:44

+0

@ Blender-Microsoft Ajax Minifier 4.74在这种情况下。 – WiredPrairie 2013-02-12 20:41:02

回答

0

你可以看看像Selenium Web Driver这样的东西,它允许你在各种环境下自动测试web应用程序。有一些云托管的虚拟机解决方案用于多环境测试,所以当它在Webkit中工作时不会被抓到,但在IE中不会被捕获。

+1

我们实际上使用它来今天进行一些自动化测试。我们的应用程序工作流程具有高度的互动性,所以它有很多工作。这涵盖了基础知识 - 但我们正在寻找更深入(更科学)的东西,理想情况。 – WiredPrairie 2013-02-13 17:37:58

1

你有没有考虑过单元测试框架,比如QUnitjs?编写单元测试将是一项相当大的工作,但最终你会有一个可重复的测试过程。

+1

这是一个有趣的想法,考虑某些情况下 - 因为我们的Web应用程序非常丰富,单元测试JavaScript UI的东西已被证明是困难的。你有什么意见来补充你已经做了什么来使用单元测试框架来测试JS/DOM重度交互吗? – WiredPrairie 2013-02-13 18:17:06

0

你绝对应该考虑使用源地图来帮助调试JavaScript的最小化。源地图还可以与JavaScript的超集一起使用,例如CoffeeScript或我最喜欢的TypeScript。

我用封编译器不仅minifies,也将创建源地图。更不用说它是最积极的并且产生最小的文件。最后,你必须知道缩小的过程以及编写兼容的代码,你的示例代码可以使用一些重构。

退房这篇文章来源地图:如何编写用于缩小率更好的代码 http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

还检查出关闭编译器的文档,它有建议: https://developers.google.com/closure/compiler/

+0

在某些情况下,我可能很有兴趣切换源代码地图调试,但我们如何做我们正在寻找的比较?你认为我们可以随时比较两个版本吗? (源代码只是最初导致此问题的代码块的一个非常简单的示例。) – WiredPrairie 2013-02-15 11:48:25

+0

我认为您需要尽可能多地了解您的情况,因此源地图只能提供帮助。在一天结束时,没有任何东西可以替代测试和任何大型网络应用程序。你绝对需要使用单元测试,自动化测试(我使用Canoo Webtest/http://webtest.canoo.com/)和手册。 至于直接比较你的老粉碎机和你的新粉碎机在做他们的工作,我不认为有任何好的方法来做到这一点。他们根据意图做了不同的事情,所以产出会有所不同,在我看来,一对一是一种有争议的事情。 – chris 2013-02-15 21:15:39

0

不是一个测试解决方案,但如何切换到TypeScript来编写像你的大JS应用程序?

我打字稿及默认的最低引擎测试了它,它工作正常。

假设你count arg是一个数字。

类型的脚本将是:

class ProcessorX { 
    ProcessX(count: number): string { 
     var value = ''; 
     value += count.toString(); 
     value += count.toString(); 
     count++; 
     return value; 
    } 
} 

将会产生JS是这样的:

var ProcessorX = (function() { 
    function ProcessorX() { } 
    ProcessorX.prototype.ProcessX = function (count) { 
     var value = ''; 
     value += count.toString(); 
     value += count.toString(); 
     count++; 
     return value; 
    }; 
    return ProcessorX; 
})(); 

然后精缩到:

var ProcessorX=function(){function n(){}return n.prototype.ProcessX=function(n){var t="";return t+=n.toString(),t+=n.toString(),n++,t},n}() 

这是对jsfiddle

如果您的countstring,那么这个fiddle

+0

较新的缩小器不再有问题。 – WiredPrairie 2013-02-20 20:00:04

0

我们使用在高级模式下关闭编译器,既minifies和修改代码,因此我们编译我们的单元测试一样,所以你可以考虑涅槃你一起测试你的代码,并像运行它。

+0

如果您的测试由于缩小而在其中产生了错误,那么测试测试的内容是什么? – Sammaye 2013-04-11 17:27:09

+0

编译器显然有针对它编写的测试,我们想要避免的是人们试图解决像someObj ['someFunc']()这样的函数,因为这将违反高级优化,并且是一个非常常见的JavaScript成语。在我们的回归测试中,另一件事(特别是完整栈的闭包)我们要确保通过重命名映射引用css名称。 – lennel 2013-04-14 09:35:40

1

听起来好像是你需要开始使用CI(持续集成环境)内的自动单元测试。 QUnit已经被抛弃了,但是真正的QUnit是一个相当弱的测试系统,它的断言至少是准系统(它甚至没有真正使用好的基于断言的语法)。它只能勉强符合TDD的要求,也不能很好地处理BDD。

我个人建议JasmineJsTestDriver(它可以使用其他UT框架,或它自己的,并且非常快速...虽然它有一些稳定性问题,我真的希望他们会修复),并设置单位可以通过多重比较检查缩小过程的测试。

一些比较可能会需要是:

  • 原代码&其功能的行为与预期
  • 相比缩小的代码(这是BDD进来,期望在精缩相同的功能性能/结果代码)
  • 我甚至会更进一步(取决于您的缩小方法),并进行测试,然后美化缩小并进行另一次比较(这会使您的测试更加稳健并更有效)。

这些类型的测试是为什么你可能会受益于像Jasmine这样的BDD-capable框架,而不是纯粹的TDD(ala你发现的视觉差异的结果是一团糟),因为你正在测试行为和比较以及功能/行为的先前/后期状态,而不仅仅是如果a在分析后是真实的并且仍然是真实的。

建立这些单元测试可能需要一段时间,但它是一个迭代方法,用一大堆代码库......快速和早期测试你的初始关键点或脆弱点,然后将测试扩展到一切(我的方式总是把我的团队设置为:从现在开始的任何事情都不被认为是完整的,并且RC除非它有单元测试......任何没有单元测试并且必须被更新/触摸/维护的旧的必须有单元测试他们很感动,这样你就可以不断改进和缩小未经测试的代码数量,同时增加代码覆盖率)。一旦你在CI中进行了单元测试并运行,你就可以将它们绑定到你的构建过程中:没有单元测试的失败构建,或者当单元测试失败时发出警报,主动监视每次检查,等等等自动生成文档与JSDoc3等等

您正在描述的问题是CI和单元测试是什么建立的,更具体地说,在你的情况下,该方法最大限度地减少了代码库......这个大小并没有让它变得更加复杂,只是让持续时间更长,让测试工作变得更长。

然后,将其与JSDoc3相结合,并且您的样式优于大多数前端商店的90%。它在这一点上对工程师来说非常强大和有用,并且变得自我延续。

我真的可以继续谈论这个话题,对于你如何接近它并让一个团队在它背后凝聚力并使之自我形成和自我延续,以及最重要的是存在很多细微差别编写可测试的代码......但从概念层面... 编写单元测试并自动化它们。总是。

太长时间的前端开发者一直半开发,没有应用实际的工程严谨和纪律。随着前端越来越强大,越来越热,它必须改变,并且正在发生变化。为前端/ RIA应用提供经过良好测试,覆盖范围广泛,自动化测试和持续集成的概念是这一变化的巨大需求之一。