Secrets of the JavaScript Ninja 边译边学(10)

Secrets of the JavaScript Ninja 边译边学(10)

2.4 The Fundamentals of a Test Suite
2.4 测试套件的基本原理

The primary purpose of a test suite is to aggregate all the individual tests that your code base might have into a single location, so that they can be run in bulk - providing a single resource that can be run easily and repeatedly.
测试套件的主要作用是将核心代码库的所有单个测试聚合到一个位置,以便它们可以批量运行-前提是批量运行的集合操作方便并且是可重复运行的。

  To better understand how a test suite works it makes sense to look at how a test suite is constructed. Perhaps surprisingly JavaScript test suites are really easy to construct and a functional one can be built in only about 40 lines of code.
  为了更好地理解测试套件是如何工作的,一个很有意义的方法是查看如何构建测试套件。事实也许让人非常惊讶:JavaScript的测试套件很容易构建,一份大约40行的代码就可以构建一个有用的测试套件。

  One would have to ask, though: Why would I want to build a new test suite? For most cases it probably isn’t necessary to write your own JavaScript test suite, there already exist a number of good-quality suites to choose from (as already shown). It can serve as a good learning experience though, especially when looking at how asynchronous testing works.
  有人可能会问,既然这样,为什么还要创建一个新的测试套件?大多数情况下,确实不需要编写自己的JavaScript测试套件,现在已经存在大量高质量的套件供我们挑选(正如之前提到的那样)。但是它可以为我们提供很好的学习经验,尤其是当我们研究异步测试如何工作的时候。

2.4.1 The assertion
2.4.1 断言

The core of a unit-testing framework is its assertion method; usually named assert() . This method usually takes a value – an expression whose premise is asserted – and a description that describes the purpose of the assertion. If the value evaluates to true , in other words is “truth-y”, then the assertion passes, otherwise it is considered a failure. The associated message is usually logged with an appropriate pass/fail indicator.
单元测试框架的核心是断言方法;该方法通常命名为assert()。该方法通常传入一个值-或者一个结果确定的表达式-以及一段描述该断言目的的说明。如果传入的值等于真,也就是"truth-y",那么断言通过,否则为失败。相关的描述说明通常使用合适的通过/失败指示器记录下结果。

  A simple implementation of this concept can be seen in Listing 2.8.
  清单2.8展示了以上概念的一份简单实现。

  The function named assert() (#1) is almost surprisingly straight-forward. It creates a new < li > element containing the description, assigns a class name pass or fail, depending upon the value of the assertion parameter ( value ), and appends the new element to a list element in the document body (#4).
  这个方法直接以assert命名(#1)。它创建了一个新的< li >标签,其中包含了描述,赋给它一个类名:pass或者fail,该值由断言的参数value确定,然后把这个元素附加到页面的一个list列表中(#4)

  The simple test suite consists of two trivial tests (#2): one that will always succeed, and one that will always fail.
  这个简单的测试套件包含两个小用例(#2):一个总是返回成功,另一个总是返回失败。
  Style rules for the pass and fail classes (#3) visually indicate success or failure using color.
  通过和失败通过不同的样式类名来区分(#3),这些样式类中定义了不同的颜色分别代表通过和失败。
  This function is simple - but it will serve as a good building block for future development, and we’ll be using this assert() method throughout this book to test various code snippets, verifying their integrity.
  该方法很简单-但却可以作为未来开发的基础版本,我们会在本书中使用该assert方法去测试各种代码片段,验证其完整性。

2.4.2 Test groups
2.4.2 测试分组

Simple assertions are useful, but really begin to shine when they are grouped together in a testing context to form test groups.
简单的断言很有用,但是当它们在一个测试上下文中组合在一起成为测试组的时候才开始真正发挥其作用。

  When performing unit testing, a test group will likely represent a collection of assertions as they relate to a single method in our API or application. If you were doing behavior-driven development the group would collect assertions by task. Either way the implementation is effectively the same.
  当作为单元测试而存在时,由于和我们的API或者应用中的单个方法相关,所以测试分组可能代表断言的集合。若进行行为驱动开发,测试分组会按照任务收集断言。无论哪种方式,实现都一样高效。

  In our sample test suite, a test group is built in which individual assertions are inserted into the results. Additionally if any assertion fails then the entire test group is marked as failing. The output in Listing 2.8 is kept pretty simple, some level dynamic control would prove to be quite useful in practice (contracting/expanding the test groups and filtering test groups if they have failing tests in them).
  在我们接下来的测试套件示例中,构建了一个测试分组,单个断言被插入其结果集中。若任何断言失败,则整个测试组标记为失败。保持了列表2.8代码的简单输出,并且加入了一定程度的动态控制,证明它确实在实践中很有用(收缩/展开测试分组,如果存在失败测试用例,可以过滤测试分组)

清单2.9 一个测试分组的实现
``` Test Suite
    
    <b>运行结果如下:</b>
    
    ![](https://img-blog.csdnimg.cn/20190628111534512.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dxeTI0OA==,size_16,color_FFFFFF,t_70)
    
    &emsp;&emsp;As we cab see seen in Listing 2.9, the implementation is really not much different from our basic assertion logging. The one major difference is the inclusion of a results variable, which holds a reference to the current test group (that way, the logging assertions are inserted correctly).
    &emsp;&emsp;如清单2.9所示,和我们之前的基础断言版本的实现区别不大。最大的区别是它包含了一个指向当前测试组的引用的结果变量(这样的话,断言可以插入到正确的地方)。
    
    <b>个人理解</b>
    这个指向所属测试组的引用是代码中的results,如下所示:
    

    var results;

    该变量在即时执行函数function开头部分定义,在test中赋值,在assert中使用。
    
    
    &emsp;&emsp;Beyond simple testing of code, another important aspect of a testing framework is handling of asynchronous operations.
    &emsp;&emsp;除了简单测试,测试框架的另一个重要方面是处理异步操作。
    
    
    2.4.3 Asynchronous Testing
    2.4.3 异步测试
    
    A daunting and complicated tasks that many developers encounter while developing a JavaScript test suite, is handling asynchronous tests. These are tests whose results will come back after a non-deterministic amount of time has passed; common examples of this situation could be Ajax requests or animations.
    许多开发者在开发JavaScript测试套件时遇到的一个棘手的问题时构建异步测试。在这些测试中,结果需要在程序运行一段不确定的时间以后才会出现;在Ajax请求或者动画中经常出现上述情形。
    &emsp;&emsp;Often handling this issue is over-though and made much more complicated than it needs be. To handle asynchronous tests we need to follow a couple of simple steps:
    &emsp;&emsp;我们通常过度处理了这个问题,让它变得比需要的更加复杂。解决异步测试问题,我们需要遵循以下几个简单的步骤:
    
    1. Assertions that are relying upon the same asynchronous operation will need to be grouped into a unifying test group.
    2. Each test group will need to be placed on a queue to be run after all the previous test groups have finished running.
    3. Thus, each test group must be capable of run asynchronously.
    
    
    
    1. 依赖于相同异步操作的断言需要分组到一个统一的测试组中。
    2. 每个测试组都需要放在一个队列中,这样就可以保证该队列在上一个测试组完成运行后才运行。
    3. 而且,每个测试组都必须具备异步运行的能力。
    
    Let’s look at the example of Listing 2.10.
    让我们来看看清单2.10中的示例。
    
    <table><tr><td bgcolor=#880015><font color=white><b>清单2.10 一个简单的异步测试的实现</b></font></td></tr></table>
    
    Test Suite
      
      <b>个人理解</b>
      该程序运行步骤如下所示:
      ![](https://img-blog.csdnimg.cn/20190701094255699.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dxeTI0OA==,size_16,color_FFFFFF,t_70)
      
      <font color=green><b>函数名后面跟()代表立即执行。比如上例中queue.shift()();queue.shift()返回的是队列中取出的函数本身的定义对象,后面跟()代表立即执行该函数。</b></font>
      
      &emsp;&emsp;Let’s break down the functionality exposed in in Listing 2.10. There are three publicly accessible functions: test() , pause() , and resume() . These three functions have the following capabilities:
      &emsp;&emsp;现在让我们来分解清单2.10中显示的函数实现。这里面由三个公共方法:test(),pause(),resume()。这三个函数具有以下功能:
      
      - test(fn) takes a function which contains a number of assertions, that will be run either synchronously or asynchronously, and places it on the queue to await execution.
      - pause() should be called from within a test function and tells the test suite to pause executing tests until the test group is done.
      - resume() unpauses the tests and starts the next test running after a short delay pu inyo place to avoid long-running code blocks.
      
      - test(fn) 是一个接收许多断言语句作为传入参数的函数,这些断言既可以异步执行也可以同步执行,该函数将其放入一个队列中等待执行。
      - pause() 应该在一个测试函数中调用该函数,通知测试套件暂停执行,直到整个测试组执行完毕。
      - resume() 在短暂的停止之后,取消暂停,开始执行下一个测试,防止长时间的代码中断。
      
      &emsp;&emsp;The one internal implementation function, runTest() , is called whenever a test is queued or dequeued. It checks to see if the suite is currently unpaused and if there's something in the queue; in which case it'll dequeue a test and try to execute it. Additionally, after the test group is finished executing it will check to see if the suite is currently 'paused' and if not (meaning that only asynchronous tests were run in the test group) it will begin
      executing the next group of tests.
      &emsp;&emsp;唯一的内部实现功能,runTest(),当测试入列或出列时被调用。它检查该套件当前是否处于暂停状态,队列里有没有待执行的测试。另外,如果测试组执行完毕,它还需要检查该套件当前是否处于暂停状态,如果不是处于暂停状态的话(也就是说测试组里面只有异步测试),才会执行下一组测试。
      
      &emsp;&emsp;We’ll be taking a closer look in chapter 8 which focuses on Timers, where we’ll make an in-depth examination of much of the nitty-gritty relating to delayed execution.
      &emsp;&emsp;我们将在第8章中更详细地介绍计时器,在第8章中,我们将深入研究与延迟执行有关的许多细节。
      
      
      2.5 Summary
      2.5 总结
      
      In this chapter we've looked at some of the basic technique surrounding debugging JavaScript code and constructing simple test cases based upon those results.
      在这一章中,我们了解了一些关于调试JavaScript代码的基本技术,并且基于这些技术构建了一些简单测试用例。
      
      &emsp;&emsp;We started off by examining how to use logging to observe the actions of our code as it is running and even implemented a convenience method that we can use to make sure that we can successfully log information in all modern browsers, despite their differences.
      &emsp;&emsp;我们首先研究了如何使用日志记录来观察代码运行时的行为,然后甚至实现了一个简便的函数,用它我们可以确保在任何现代浏览器中都能成功地记录信息,不论这些浏览器之间存在多少差异。
      
      &emsp;&emsp;We then explored how to use breakpoints to halt the execution of our code at a certain point, allowing us to take a look around at the state within which the code is executing.
      &emsp;&emsp;然后,我们研究了如何使用断点在某一点上停止代码的执行,从而允许我们查看各项代码运行时状态。
      
      &emsp;&emsp;Our attention then turned to test generation, defining and focusing on the attributes of good tests: repeatability, simplicity and independence. The two major types of testing, deconstructive and constructive testing were then examined.
      &emsp;&emsp;然后,我们将注意力转向构建测试,定义并关注好的测试的属性:可重复性、简单性和独立性。然后分析了两种主要的测试类型:解构测试和构造性测试。
      
      &emsp;&emsp;Data collected regarding how the JavaScript community is using testing was presented, and we took a brief survey of existing test frameworks that you might want to explore and adopt should you want use a formalized testing environment.
      &emsp;&emsp;介绍了收集到的有关JavaScript社区如何使用测试的数据,我们对现有的测试框架进行了简短的调查,如果您希望使用正式的测试环境,那么您可能希望探索并采用这些测试框架。
      
      &emsp;&emsp;Building upon that, we introduced the concept of the assertion, and created a simple implementation that will be used throughout the remainder of this book to verify that our code does what we intend for it to do.
      &emsp;&emsp;在此基础上,我们引入断言的概念,并创建了一个简单的实现,该实现将在本书的其余部分中使用,以验证我们的代码是否按照希望的方式执行。
      
      &emsp;&emsp;Finally, we looked at how to construct a simple test suite capable of handling asynchronous test cases. Altogether, these techniques will serve as an important cornerstone to the rest of your development with JavaScript.
      &emsp;&emsp;最后,我们研究了如何构建一个能够处理异步测试用例的简单测试套件。总之,这些技术将成为您使用JavaScript开发其余部分的重要基础。
      
      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

      当前余额3.43前往充值 >
      需支付:10.00
      成就一亿技术人!
      领取后你会自动成为博主和红包主的粉丝 规则
      hope_wisdom
      发出的红包
      实付
      使用余额支付
      点击重新获取
      扫码支付
      钱包余额 0

      抵扣说明:

      1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
      2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

      余额充值