16

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

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

(人生教训:除非你真的确信你需要新版本,否则不要升级 JS 缩小器。)

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 代码。

我们正在寻找一种方法来测试缩小过程,而不是“再次彻底地测试所有内容,然后重复”。我们想在这个过程中应用更多的严谨/科学。

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

更新:

我们的一个想法是:

  1. 用旧版本缩小
  2. 美化它
  3. 用新版本缩小,
  4. 美化,和
  5. 视觉上的差异。

这看起来确实是个好主意,但是差异如此普遍,以至于差异工具几乎将每一行都标记为不同。

4

6 回答 6

1

在我看来,您需要开始在 CI(持续集成环境)中使用自动化单元测试。QUnit 已经被抛弃了,但实际上 QUnit 是一个非常弱的测试系统,它的断言至少是准系统(它甚至没有真正使用好的基于断言的语法)。它只能勉强称得上 TDD,也不能很好地处理 BDD。

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

一些比较可能需要:

  • 原始代码及其功能按预期运行
  • 与缩小代码相比(这是 BDD 的用武之地,期望在缩小代码中具有相同的功能性能/结果)
  • 我什至会更进一步(取决于您的缩小方法),并进行一个测试,然后美化缩小并进行另一次比较(这使您的测试更加健壮,更加确保有效性)。

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

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

一旦你在 CI 中启动并运行了单元测试,你就可以将它们绑定到你的构建过程中:失败没有单元测试的构建,或者当单元测试失败时发送警报,主动监控每个签入等等。使用 JSDoc3 等自动生成文档等。

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

然后,将它与 JSDoc3 结合起来,你的样式比 90% 的大多数前端商店都好。在那时,它对工程师来说非常强大和有用,并且可以自我延续。

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

长期以来,前端开发人员一直在半途而废,没有应用实际的工程严谨性和纪律。随着前端变得越来越强大和热门,这必须改变,并且正在改变。前端/RIA 应用程序的良好测试、良好覆盖、自动化测试和持续集成的概念是这种变化的巨大需求之一。

于 2013-02-22T20:16:01.370 回答
1

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

于 2013-02-13T16:51:06.113 回答
0

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

于 2013-02-20T18:02:30.317 回答
0

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

我用 TypeScript 及其默认的最小引擎对其进行了测试,它运行良好。

假设您的countarg 是一个数字。

类型脚本将是:

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上。

如果你count是一个string,那么这个小提琴

于 2013-02-20T17:43:08.997 回答
0

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

于 2013-02-13T16:50:15.990 回答
0

您绝对应该考虑使用源映射来帮助调试最小化的 JavaScript。源映射也适用于 JavaScript 的超集,例如 CoffeeScript 或我最喜欢的 TypeScript。

我使用闭包编译器,它不仅会缩小,还会创建源映射。更不用说它是最激进的并且产生最小的文件。最后,您必须知道缩小过程中发生了什么并编写兼容的代码,您的示例代码可以使用一些重构。

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

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

于 2013-02-15T06:01:35.463 回答