本期,我们要讨论的话题是 JavaScript 的测试,以检查组件的状态和工作方式是否符合预期,还会介绍一个可以方便编写测试用例的测试方法。这里说的测试当然是使用自动化的测试手段,这是软件质量保证(QA)的重要环节。就本系列文章介绍的 Smart Queue 来说,我们的测试目标包括:
- Task 对象的创建:第二期的代码提供了多种创建方式,需要测试对象创建后的状态。
- Queue 内的任务运行次序:我们提供了两种改变运行次序的方式:优先级和依赖配置,同样也要测试各种配置对次序的影响。
对于第一个目标,只需检查对象创建后的属性是否符合预期即可。我们已经多次提到“符合预期”,断言(Assert)正是为此而设计的。简单的说,断言就是确保所测试的表达式结果为“真”,否则,以某种方式通知测试人员,并帮助其定位断言失败的测试用例。
第二个目标稍稍有点复杂。由于我们在组件编码实现的时候,将排序后的队列(<font face="新宋体">_sorted</font>
)隐藏在了闭包中,所以外部是无法访问的。有两种方法可以考虑:(1)重构代码,增加代码的可测试性,又有两种重构方法:(a)设置 debug 开关,打开时将 <font face="新宋体">_sorted</font>
暴露给外部;(b)增加独立文件,以构建的方式拼接代码最终生成一个测试版本。(2)测试行为的结果而不是过程,前一种方法实质上是深入到组件的运行时状态,而这个方法只是检查组件的运行结果。本期选用后一种种测试方式,第一种测试方式留给有兴趣的读者练习:)
需要说明的是,我个人不赞成第一种的方法a. 为什么呢?我先说一下这个任务队列的设计理念:
- 它只是一个队列,只负责“按需”调整任务的运行次序,不关注任务的个体细节。换句话说,它操作整体的任务,而不关心任务具体的行为和表现。
- 它是个安全的队列,使用者(第一期提到的“客户”)可以放心把任务添加进去,不用担心这个任务信息会被其他客户看到。需要说明的是,第二期实现代码中有
<font face="新宋体">SmartQueue.Queue = [[], [], []]</font>
, 结果是外部可以访问到队列项。代码仅供介绍之用,你可以安全地删除<font face="新宋体">SmartQueue.Queue = </font>
来达成安全控制。
回到刚才讨论的话题,设置 debug 开关后,任务信息就潜在的泄漏可能性。进一步地,继续改造代码也可以达成在使用 debug 开关时的安全性,做法是将开关的控制放在 SmartQueue 的构造函数中,这样要求 SmartQueue 实现 Singleton 模式(见上一篇文章);一旦创建对象后,不允许修改闭包内的 debug 标记。
在编写具体测试代码前,我们设计了一个测试方法,以简化测试代码(主要是用例)的编写。简单地说,就是将测试用例与测试本身的代码分离——前者以语义良好的方式编写,后者是一次性编写,用于处理前者设定的测试用例。用例编写者需要写格式形如这样的代码:
<span style="COLOR: #b000b0"><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0"> </span><span style="COLOR: #0000c0">id</span><span style="COLOR: #b000b0">=</span><span style="COLOR: #008000">"J_test_cases"</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">pre</span><span style="COLOR: #b000b0">></span>task = new sq.Task({fn: function() { log('unamed') }})<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">pre</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>typeof task.fn === 'function'<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.name === 't0'<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.level === 1<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.dependencies.length === 0<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.context == window<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">pre</span><span style="COLOR: #b000b0">></span>task = new sq.Task({fn: function() { log('unamed') }, name: 'hello'})<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">pre</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.name === 'hello'<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span>task.level === 1<span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">li</span><span style="COLOR: #b000b0">></span> <span style="COLOR: #b000b0"></span><span style="COLOR: #c00000">ul</span><span style="COLOR: #b000b0">></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
ul li pre (CSS 选择器路径,下同)中写要测试的代码,相当于前置操作;ul ul li 中对这个代码进行断言测试,可以编写多条断言。这里建议对基本数据类型使用 <font face="新宋体">===</font>
和 <font face="新宋体">!===</font>
运算符以加强对数据类型的预期判断。
接下来,我们编写两个 helper 方法用来输出和测试:
<span style="COLOR: #b000b0">function</span> log(str) { node.value += str + <span style="COLOR: #008000">'</span><span style="COLOR: #606060">\n</span><span style="COLOR: #008000">'</span>; } <span style="COLOR: #b000b0">function</span> assert(expression) { <span style="COLOR: #0000c0">var</span> flag; eval(<span style="COLOR: #008000">'flag = '</span> + expression); <span style="COLOR: #c00000">return</span> <span style="COLOR: #c00000">typeof</span>(flag) === <span style="COLOR: #008000">'boolean'</span> && flag; }
<font face="新宋体">log</font>
用来向文本框追加信息,<font face="新宋体">assert</font>
用来测试传入表达式的值。测试方法如下(这里使用了 jQuery):
<span style="COLOR: #0000c0">var</span><span style="COLOR: #606060"> sq = SmartQueue, task, total = </span><span style="COLOR: #008000">0</span><span style="COLOR: #606060">, passed = </span><span style="COLOR: #008000">0</span><span style="COLOR: #606060">, failed = </span><span style="COLOR: #008000">0</span><span style="COLOR: #606060">;</span> <span style="COLOR: #606060">$</span>(<span style="COLOR: #008000">'#J_test_cases'</span><span style="COLOR: #606060">).children</span>(<span style="COLOR: #606060">).each</span>(<span style="COLOR: #b000b0">function</span>(index)<span style="COLOR: #606060"> </span>{ eval($(<span style="COLOR: #008000">'pre'</span>, <span style="COLOR: #0000c0">this</span>).text()); task.register(); $(<span style="COLOR: #008000">'li'</span>, <span style="COLOR: #0000c0">this</span>).each(<span style="COLOR: #b000b0">function</span>() { <span style="COLOR: #0000c0">var</span> item = $(<span style="COLOR: #0000c0">this</span>); <span style="COLOR: #0000c0">var</span> flag = assert(item.text()); <span style="COLOR: #c00000">if</span>(flag) passed ++; <span style="COLOR: #c00000">else</span> failed ++; item.prepend((flag ? <span style="COLOR: #008000">'<font color="green">[PASS]</font>'</span> : <span style="COLOR: #008000">'<font color="red">[FAIL]</font>'</span>) + <span style="COLOR: #008000">' '</span>); total++; }).wrap(<span style="COLOR: #008000">'<pre class="brush:php;toolbar:false">'); }).end().before('
Total: '
+ total + ', passed: '+ passed +', failed: ' + failed + ''); sq.fire();这个结构还可改进一下,比如输出测试说明而不是具体的代码,也可以增加后置操作,这里就不再演示了。你还可以查看完整的测试页面,含有 23 个测试用例和完整的测试实现。
~~~~~~~~~~~~~~~ 팔괘분할선 ~~~~~~~~~~~~
생각하고 행동하는 즐거움을 경험하는 이 기사 시리즈는 끝났지만 이는 시작에 불과합니다. 작은 실용적인 컴포넌트를 구현하는 전 과정을 거치며 자바스크립트 세계의 설렘을 경험해 봤습니다~

Golang中的数据库测试技巧引言:在开发应用程序时,数据库测试是一个非常重要的环节。合适的测试方法可以帮助我们发现潜在的问题并确保数据库操作的正确性。本文将介绍Golang中的一些常用数据库测试技巧,并提供相应的代码示例。一、使用内存数据库进行测试在编写数据库相关的测试时,我们通常会面临一个问题:如何在不依赖外部数据库的情况下进行测试?这里我们可以使用内存

如何使用MTR进行MySQL数据库的可靠性测试?概述:MTR(MySQL测试运行器)是MySQL官方提供的一个测试工具,可以帮助开发人员进行MySQL数据库的功能和性能测试。在开发过程中,为了确保数据库的可靠性和稳定性,我们经常需要进行各种测试,而MTR提供了一种简单方便且可靠的方法来进行这些测试。步骤:安装MySQL测试运行器:首先,需要从MySQL官方网

如何使用Selenium进行Web自动化测试概述:Web自动化测试是现代软件开发过程中至关重要的一环。Selenium是一个强大的自动化测试工具,可以模拟用户在Web浏览器中的操作,实现自动化的测试流程。本文将介绍如何使用Selenium进行Web自动化测试,并附带代码示例,帮助读者快速上手。环境准备在开始之前,需要安装Selenium库和Web浏览器驱动程

在Web开发中,PHP是一种流行的语言,因此对于任何人来说,对PHP进行单元测试是一个必须掌握的技能。本文将介绍什么是PHP单元测试以及如何进行PHP单元测试。一、什么是PHP单元测试?PHP单元测试是指测试一个PHP应用程序的最小组成部分,也称为代码单元。这些代码单元可以是方法、类或一组类。PHP单元测试旨在确认每个代码单元都能按预期工作,并且能否正确地与

随着Web应用程序规模的不断扩大,PHP语言的应用也越来越广泛。在软件开发过程中,自动化测试可以大大提高开发效率和软件质量。而Jenkins是一个可扩展的开源自动化服务器,它能够自动执行软件构建、测试、部署等操作,今天我们来看一下在PHP开发中如何使用Jenkins进行自动化测试。一、Jenkins的安装和配置首先,我们需要在服务器上安

ChatGPT的出现,使中文社区意识到与国际领先水平的差距。近期,中文大模型研发如火如荼,但中文评价基准却很少。在OpenAIGPT系列/GooglePaLM系列/DeepMindChinchilla系列/AnthropicClaude系列的研发过程中,MMLU/MATH/BBH这三个数据集发挥了至关重要的作用,因为它们比较全面地覆盖了模型各个维度的能力。最值得注意的是MMLU这个数据集,它考虑了57个学科,从人文到社科到理工多个大类的综合知识能力。DeepMind的Gopher和Chinchi

如何使用Python进行软件安全测试随着互联网的发展,软件安全问题日益凸显,软件安全测试也成为了越来越重要的一项工作。而Python作为一种流行的脚本语言,具备简单易学、开发效率高的特点,因此被广泛用于软件安全测试领域。本文将介绍如何使用Python进行软件安全测试,帮助读者更好地应对软件安全挑战。首先,我们需要了解软件安全测试的基本概念和分类。软件安全测试

如何在命令行中测试MySQL连接的高并发性能?随着互联网应用的不断普及,数据库的高并发性能成为了很多需求的关注点之一。而MySQL作为一个流行的开源数据库,其高并发性能也是被广泛关注的。在测试MySQL连接的高并发性能之前,我们需要先明确一些概念和准备工作:并发连接:指的是同时有多个客户端与数据库建立连接,并且这些连接同时进行数据库操作。连接数限制:MySQ


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

드림위버 CS6
시각적 웹 개발 도구

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

ZendStudio 13.5.1 맥
강력한 PHP 통합 개발 환경

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

DVWA
DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

뜨거운 주제



