测试驱动javascript开发 -- 5.性能测试

简介:   自动化测试另外一个比较重要的内容点是性能测试,很多问题可能有不止一种解决方案,很多时候并不知道哪个是最好的解决方案。例如有很多创建javascript对象的方法,使用javascript构造器、使用函数的方法或者使用闭包。

  自动化测试另外一个比较重要的内容点是性能测试,很多问题可能有不止一种解决方案,很多时候并不知道哪个是最好的解决方案。例如有很多创建javascript对象的方法,使用javascript构造器、使用函数的方法或者使用闭包。我们可能会从可测试化、灵活性和性能的角度去考虑使用哪种方式。足见性能是相当重要的一点。

  1.基准和相对性能

  当一个问题我们有两个以上的解决方案的时候,判断哪个解决方案更好的原则很简单,就是哪个的性能更好。判断的原则也很简单:1.创建new Date()作为开始时间;2.执行要衡量的代码;3.代码执行完毕,创建new Date()作为结束时间,减去开始时间算出总时长;4.替换执行代码,重复上述步骤;5.比较各种方案的执行时长。

  每个要比较的代码我们需要执行很多次,通常会把他们放在一个循环中。因为windows xp和vista操作系统的浏览器的timer的间隔时间是15ms,让这个问题变的更加复杂,测试会变的相当不准确,所以我们需要保证测试代码运行时长在500ms以上。

  下面是我们用来做性能测试的代码,文件为benchmark.js:

var ol;
function
runBenchmark(name, test) {   if (!ol) {     ol = document.createElement("ol");     document.body.appendChild(ol);   }   setTimeout(function () {     var start = new Date().getTime();     test();     var total = new Date().getTime() - start;     var li = document.createElement("li");     li.innerHTML = name + ": " + total + "ms";     ol.appendChild(li);   }, 15); }

  下面的代码使用runBenchmark()用来做测试,文件名为loops.js:

var loopLength = 500000;
// 填充循环数组
var array = [];
for (var i = 0; i < loopLength; i++) {
  array[i] = "item" + i;
}
function forLoop() {
  for (var i = 0, item; i < array.length; i++) {
    item = array[i];
  }
}function forLoopCachedLength() {
  for (var i = 0, l = array.length, item; i < l; i++) {
    item = array[i];
  }
}
function forLoopDirectAccess() {
  for (var i = 0, item; (item = array[i]); i++) {
  }
}
function whileLoop() {
  var i = 0, item;
  while (i < array.length) {
    item = array[i];
    i++;
  }
}
function whileLoopCachedLength() {
  var i = 0, l = array.length, item;
  while (i < l) {
    item = array[i];
    i++;
  }
}
function reversedWhileLoop() {
  var l = array.length, item;
  while (l--) {
    item = array[l];
  }
}
function doubleReversedWhileLoop() {
  var l = array.length, i = l, item;
  while (i--) {
    item = array[l - i - 1];
  }
}

// Run tests
runBenchmark("for-loop", forLoop);
runBenchmark("for-loop, cached length", forLoopCachedLength);
runBenchmark("for-loop, direct array access", forLoopDirectAccess);
runBenchmark("while-loop", whileLoop);
runBenchmark("while-loop, cached length property", whileLoopCachedLength);
runBenchmark("reversed while-loop", reversedWhileLoop);
runBenchmark("double reversed while-loop", doubleReversedWhileLoop);

  使用setTimeout方法的目的是,在测试中避免浏览器的堵塞。因为浏览器只有一个单线程,他用这一个线程完成javascript的运行、事件的触发和页面的渲染工作。timer则为浏览器提供了一个任务队列,可以用他来处理长时间运行的工作,这样就可以避免在运行测试代码时弹出超时警告。

  下面我们看看loops.html页面的内容:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>Relative performance of loops</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
<body>
  <h1>Relative performance of loops</h1>
  <script type="text/javascript" src="benchmark.js"></script>
  <script type="text/javascript" src="loops.js"></script>
</body>
</html>

  所有的测试做的事情都差不多,遍历数组,并访问每个成员。通过测试,我们可以看到哪种方式效率最高。

  我们可以把runBenchmark方法做一下重构:

var benchmark = (function () {
  function init(name) {
    var heading = document.createElement("h2");
    heading.innerHTML = name;
    document.body.appendChild(heading);
    var ol = document.createElement("ol");
    document.body.appendChild(ol);
    return ol;
  }
  
function runTests(tests, view, iterations) {     for (var label in tests) {       if (!tests.hasOwnProperty(label) || typeof tests[label] != "function") {         continue;       }       (function (name, test) {         setTimeout(function () {           var start = new Date().getTime();           var l = iterations;           while (l--) {             test();           }           var total = new Date().getTime() - start;           var li = document.createElement("li");           li.innerHTML = name + ": " + total + "ms (total), " + (total / iterations) + "ms (avg)";           view.appendChild(li);         }, 15);       }(label, tests[label]));     }   }
  
function benchmark(name, tests, iterations) {     iterations = iterations || 1000;     var view = init(name);     runTests(tests, view, iterations);   }
  
return benchmark; }());

  使用benchmark也很简单,如下:

var loopLength = 100000;
var array = [];
for (var i = 0; i < loopLength; i++) {
  array[i] = "item" + i;
}
benchmark("Loop performance", {
  "for-loop": function () {
    for (var i = 0, item; i < array.length; i++) {
      item = array[i];
    }
  },
  "for-loop, cached length": function () {
    for (var i = 0, l = array.length, item; i < l; i++) {
      item = array[i];
    }
  },
  // ...
  "double reversed while-loop": function () {
    var l = array.length, i = l, item;
    while (i--) {
      item = array[l - i - 1];
    }
  }
}, 1000);

  我们也可以为benchmark扩展更多的功能,例如把最快和最慢的测试用高亮的方式显示:

// 记录次数
var times;
function runTests (tests, view, iterations) {
  // ...
  (function (name, test) {
    // ...
    var total = new Date().getTime() - start;
    times[name] = total;
    // ...
  }(label, tests[label]));
  // ...
}
function highlightExtremes(view) {   // The timeout is queued after all other timers, ensuring   // that all tests are finished running and the times   // object is populated   setTimeout(function () {     var min = new Date().getTime();     var max = 0;     var fastest, slowest;     for (var label in times) {       if (!times.hasOwnProperty(label)) {         continue;       }       if (times[label] < min) {         min = times[label];         fastest = label;       }       if (times[label] > max) {         max = times[label];         slowest = label;       }     }     var lis = view.getElementsByTagName("li");     var fastRegexp = new RegExp("^" + fastest + ":");     var slowRegexp = new RegExp("^" + slowest + ":");     for (var i = 0, l = lis.length; i < l; i++) {       if (slowRegexp.test(lis[i].innerHTML)) {         lis[i].style.color = "#c00";       }       if (fastRegexp.test(lis[i].innerHTML)) {         lis[i].style.color = "#0c0";       }     }   }, 15); } // Updated benchmark function function benchmark (name, tests, iterations) {   iterations = iterations || 1000;   times = {};   var view = init(name);   runTests(tests, view, iterations);   highlightExtremes(view); }

 

  2.分析和定位瓶颈

  很多浏览器提供了调试工具,例如firefox的firebug。这些工具可以为我们提供很多信息,帮助我们跟踪代码,判断代码中的问题。例如下图就是使用firebug的实例。

 

代码下载:

目录
相关文章
|
人工智能 自然语言处理 测试技术
从人工到AI驱动:天猫测试全流程自动化变革实践
天猫技术质量团队探索AI在测试全流程的落地应用,覆盖需求解析、用例生成、数据构造、执行验证等核心环节。通过AI+自然语言驱动,实现测试自动化、可溯化与可管理化,在用例生成、数据构造和执行校验中显著提效,推动测试体系从人工迈向AI全流程自动化,提升效率40%以上,用例覆盖超70%,并构建行业级知识资产沉淀平台。
从人工到AI驱动:天猫测试全流程自动化变革实践
|
数据采集 人工智能 监控
人工智能驱动的软件工程:测试左移的崛起价值
本文探讨了人工智能驱动下测试左移理念在软件工程中的重要性,分析测试工程师在需求评估、AI代码生成及遗留系统优化中的关键作用,揭示AI带来的挑战与机遇,并指出测试工程师需提升技能、关注合规与可维护性,以在AI时代保障软件质量。
746 89
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的1024QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的1024QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同SNR条件下的性能测试。1024QAM调制将10比特映射到复平面上的1024个星座点之一,实现高效数据传输。硬件测试结果表明,在SNR=32dB和40dB时,系统表现出良好的性能。Verilog核心程序展示了各模块的连接与功能实现。
490 7
|
JavaScript 前端开发 开发者
JavaScript:驱动现代Web的核心引擎
JavaScript:驱动现代Web的核心引擎
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
JavaScript 前端开发 物联网
JavaScript:驱动现代Web的核心引擎
JavaScript:驱动现代Web的核心引擎
|
传感器 人工智能 JavaScript
鸿蒙开发:DevEcoTesting中的稳定性测试
DevEcoTesting主要的目的也是用于软件的测试,可以让开发者无需复杂的配置,即可一键执行测试任务,同时提供了测试报告和分析,无论是对于开发者还是测试同学来说,都是一个非常方便的工具。
478 3
鸿蒙开发:DevEcoTesting中的稳定性测试
|
存储 测试技术 API
数据驱动开发软件测试脚本
今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。
500 0
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
3027 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
敏捷开发 运维 数据可视化
DevOps看板工具中的协作功能:如何打破开发、测试与运维之间的沟通壁垒
在DevOps实践中,看板工具通过可视化任务管理和自动化流程,提升开发与运维团队的协作效率。它支持敏捷开发、持续交付,助力团队高效应对需求变化,实现跨职能协作与流程优化。