如何测试JavaScript缩小输出

时间:2013-02-12 20:34:09

标签: javascript unit-testing

我们最近升级到了较新版的JavaScript缩小库。

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

(生命教训:除非你确信你需要新版本,否则不要升级JS minifiers。)

minifier用于客户端JavaScript代码,重点关注与DOM相关的活动,而不是“业务逻辑”。

缩小器升级破坏的简化示例:

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到AST库,但鉴于可以对缩小代码进行更改的性质,它会产生太多的误报。

我们还考虑过尝试编写代表性测试,但这似乎是一项永无止境的任务(可能会错过案例)。

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

我们正在寻找一种测试缩小过程的方法,而不是“再次测试所有内容,彻底,重复”。我们想对这个过程采用更严格/更科学的方法。

理想情况下,如果我们有更好的科学方法进行测试,我们可以尝试使用多个缩小器,而不必担心会以新的微妙方式破坏我们的代码。

更新:

我们的一个想法是:

  1. 使用旧版本进行缩小
  2. 美化它
  3. 缩小新版本,
  4. 美化,
  5. 视觉上的差异。
  6. 这似乎是一个好主意,但差异非常普遍,差异工具几乎将每一行标记为不同。

6 个答案:

答案 0 :(得分:1)

您是否考虑过单位测试框架,例如QUnitjs?编写单元测试会有相当多的工作,但最终你会有一个可重复的测试程序。

答案 1 :(得分:1)

听起来我需要开始在CI(持续集成环境)中使用自动单元测试。 QUnit已被抛出,但实际上QUnit是一个非常弱的测试系统,它的断言至少是准系统(它甚至没有真正使用一个好的基于断言的语法)。它只是略有资格作为TDD,也不能很好地处理BDD。

我个人推荐JasmineJsTestDriver(它可以使用其他UT框架,或者它自己的,并且速度非常快......虽然它有一些稳定性问题我真的希望它们' d fix),以及可通过多重比较检查缩小过程的设置单元测试。

可能需要进行一些比较:

  • 原始代码&其功能符合预期
  • 与缩小代码相比(这是BDD的用武之地,期望在缩小代码时获得相同的功能性能/结果)
  • 我甚至更进一步(取决于你的缩小方法),并进行测试,然后美化缩小并进行另一次比较(这使你的测试更加健壮,更有效地保证)。

这些类型的测试就是为什么你可能会受益于像Jasmine这样的支持BDD的框架,而不仅仅是纯粹的TDD(你发现视觉差异的结果很糟糕),因为你正在测试行为和比较以及功能/行为的先前/后置状态,不仅仅是a是真的并且在被解析后仍然是真的。

设置这些单元测试可能需要一段时间,但它是一个具有大量代码库的迭代方法...快速和早期测试您的初始关键阻塞点或脆弱点,然后将测试扩展到所有(我的方式)总是设置我的团队的是,从这一点开始的任何事情都不被认为是完整的和RC,除非它有单元测试......没有单元测试且必须更新/触摸/维护的任何旧的必须在他们编写单元测试时编写感动,以便您以更易于管理和逻辑的方式不断改进和缩减未经测试的代码量,同时增加代码覆盖率。)

在CI中进行单元测试并运行后,您可以将它们绑定到构建过程中:没有单元测试的失败构建,或者单元测试失败时发出警报,主动监视每个签入等等。使用JSDoc3等自动生成文档。

您所描述的问题是CI和单元测试的构建方式,更具体地说,在您的情况下,该方法可以最大限度地减少代码库大小的影响...大小不会使其更复杂,只是使让测试工作时间更长的持续时间。

然后,将它与JSDoc3结合起来,你的造型优于90%的大多数前端商店。它在当时对工程师来说非常强大和有用,并且它变得自我延续。

我真的可以继续谈论这个话题,对你如何处理它并让一个团队团结起来并使其自我形成和自我延续有很多细微差别,最重要的是写作可测试代码......但是从概念层面...... 编写单元测试并自动化它们。总是

太久以来,开发人员一直在努力发展,而不是应用实际的工程严谨和纪律。随着前端变得越来越强大和热门,这必须改变,并且正在发生变化。前端/ RIA应用程序经过良好测试,覆盖良好,自动化测试和持续集成的概念是这一变化的巨大需求之一。

答案 2 :(得分:0)

您可以查看Selenium Web Driver之类的内容,它允许您在各种环境中自动执行Web应用程序的测试。有一些用于进行多环境测试的云托管VM解决方案,因此当它在Webkit中工作但在IE中不工作时,您不会被抓住。

答案 3 :(得分:0)

您一定要考虑使用源映射来帮助调试最小化的JavaScript。源地图也适用于JavaScript的超集,例如CoffeeScript或我最喜欢的TypeScript。

我使用闭包编译器,它不仅会缩小,还会创建源映射。更不用说它是最具侵略性的并且产生最小的文件。最后,您必须知道缩小和编写兼容代码的内容,您的示例代码可能会使用一些重构。

在源地图上查看这篇文章: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

还查看了关闭编译器的文档,它有关于如何编写更好的缩小代码的建议: https://developers.google.com/closure/compiler/

答案 4 :(得分:0)

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

我使用TypeScript及其默认的min引擎测试了它,它运行正常。

假设您的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

答案 5 :(得分:0)

我们在高级模式下使用闭包编译器来缩小和更改代码,因此我们也编译单元测试,因此您可以考虑将测试与代码一起缩小并运行它。

相关问题