ICSE (2022). Nessie的阅读记录

题目:

Nessie: Automatically Testing JavaScript APIs with Asynchronous Callbacks

问题 :几个不理解的名词

1:什么是JavaScript APIs?

客户端JavaScript中有很多可用的API — 他们本身并不是JavaScript语言的一部分,却建立在JavaScript语言核心的顶部,为使用JavaScript代码提供额外的超强能力。他们通常分为两类:

浏览器API内置于Web浏览器中,能从浏览器和电脑周边环境中提取数据,并用来做有用的复杂的事情 。例如Geolocation API提供了一些简单的JavaScript结构以获得位置数据,因此您可以在Google地图上标示您的位置。在后台,浏览器确实使用一些复杂的低级代码(例如C++)与设备的GPS硬件(或可以决定位置数据的任何设施)通信来获取位置数据并把这些数据返回给您的代码中使用浏览器环境;但是,这种复杂性通过API抽象出来,因而与您无关。
第三方API缺省情况下不会内置于浏览器中,通常必须在Web中的某个地方获取代码和信息。例如Twitter API 使您能做一些显示最新推文这样的事情,它提供一系列特殊的结构,可以用来请求Twitter服务并返回特殊的信息。

2:什么是Asynchronous ?与synchronous的区别?

同步 顺序执行
异步,不等待,跳过执行,执行完返回。

3:什么是 Callbacks ? Asynchronous Callbacks ?
异步回调就是发起请求后,不等待响应就去先干别的事
相对于同步就是必须等到响应该请求后才能做别的事



ABSTRACT


第1句

原文:
Previous algorithms for feedback-directed unit test generation iteratively create sequences of API calls by executing partial tests and by adding new API calls at the end of the test.

译文:
以前的反馈导向单元测试生成算法 通过执行部分测试和在测试结束时添加新的 API 调用来迭代地创建 API 调用序列。

问题

1.1:什么是API calls ?
1.2:什么是 “iteratively create”-- “迭代的创建”?


第2句

原文:
These algorithms are challenged by a popular class of APIs: higher-order functions that receive callback arguments, which often are invoked asynchronously.

译文:
这些算法受到一类流行的 API 的挑战:接收回调参数的高阶函数,这些函数通常被异步调用。

问题:什么高阶函数这么麻烦? 需要异步调用

当一个函数a以一个函数作为参数或者以一个函数作为返回值时,那么函数a就是高阶函数


第3句

原文
Existing test generators cannot effectively test such APIs because they only sequence API calls, but do not nest one call into the callback function of another

译文
现有的测试生成器无法有效地测试此类 API,因为它们仅对 API 调用进行排序,但不会将一个调用嵌套到另一个调用的回调函数中

问题:什么是测试生成器 test generators?


第4句

原文
This paper presents Nessie, the first feedback-directed unit test generator that supports nesting of API calls and that tests asynchronous callbacks.

译文
本文介绍了 Nessie,这是第一个支持 API 调用嵌套和测试异步回调的反馈导向单元测试生成器

问题: 什么是 nesting of API calls? API 调用嵌套?



第5句

原文
Nesting API calls enables a test to use values produced by an API that are available only once a callback has been invoked, and is often necessary to ensure that methods are invoked in a specific order.

译文
嵌套 API 调用使得测试能够使用由 API 生成的值,这些值仅在调用回调后可用,并且通常需要确保以特定顺序调用方法。

问题 :这句话说了啥? 是不是说嵌套API 调用很牛X,有很大优势或者好处?

如果是? 好在哪里了?



第6句

原文
The core contributions of our approach are a tree-based representation of unit tests with callbacks and a novel algorithm to iteratively generate such tests in a feedback-directed manner.

译文
我们方法的核心贡献是基于树的带有回调的单元测试表示,以及一种以反馈导向的方式迭代生成此类测试的新算法。

问题:核心贡献是啥? 是一种表示and一种算法?



第7句

原文
We evaluate our approach on ten popular JavaScript libraries with both asynchronous and synchronous callbacks. The results show that, in a comparison with LambdaTester, a state of the art test generation technique that only considers sequencing of method calls, Nessie finds more behavioral differences and achieves slightly higher coverage.

译文
我们在十个流行的具有异步和同步回调的 JavaScript 库上评估我们的方法。结果表明,与仅考虑方法调用顺序的最先进的测试生成技术 LambdaTester 相比,Nessie 发现了更多的行为差异并实现了略高的覆盖率。

问题 :做了评估,Nessie的更好在哪里?

1:发现了更多的差异?什么差异?
2:更高的覆盖率,啥覆盖率?



第8句

原文
Notably, Nessie needs to generate significantly fewer tests to achieve and exceed the coverage achieved by the state of the art.

译文
值得注意的是,Nessie 需要生成更少的测试来达到并超过现有技术所达到的覆盖率。

问题: 又是经典的“Notably”,强调Nessis的新亮点,需要更少的测试就能实现并超过其他。



小结

abstract一共讲了8句话。

第1、2、3句讲了别人的2个不好:以前的算法(反馈导向单元测试生成算法)麻烦、不好; 现在的test generators 不好,无法有效测试此类API(异步调用)。

第4、5 句指出自己设计的Nessis很好,自己设计了一个 单元测试生成器,支持很多,有很多优良特性。

第6句简要介绍自己的核心贡献:一个算法+一个表示。
第7句 做了测试评估 ,侧面证明Nessi很好。
第8句 又一次指出,Nessi的新亮点:需要更少的测试。




一、INTRODUCTION

第1段

第1句

原文
Test generation is an important technique to automatically test libraries by creating unit-level tests.
The generated tests typically consist of a sequence of calls to functions in an API under test.

译文
测试生成是通过创建单元级测试来自动测试库的重要技术。
生成的测试通常包括对被测 API 中函数的一系列调用。

问题:“Test generation” 是一项技术,这项技术可以产生“测试”,产生的这些“测试”包含对被测API函数的一些调用???


第2句


The values passed as arguments to each function call in such a sequence may be chosen randomly, or values returned by previous calls in the sequence can be used, to facilitate the testing of dependent API functions.

译文
在这样的序列中作为参数传递给每个函数调用的值可以是随机选择的,或者可以使用序列中先前调用返回的值,以方便对相关 API 函数的测试。

问题: 这一句和前面那句是啥联系?

values(…作为参数传递给每个函数调用)可能(可以)随机选择,或者使用先前调用返回的值,目的是啥?
方便对相关API函数进行测试????
这句话的都是啥意思???


第3句

原文
Different test generators take different approaches for selecting which functions to call and which arguments to pass into them, e.g., random inputs [10, 12], feedback from executions [13, 29, 30], and symbolic reasoning.

译文
不同的测试生成器采用不同的方法来选择调用哪些函数以及将哪些参数传递给它们,例如,随机输入 [10, 12]、来自执行的反馈 [13, 29, 30] 和符号推理。

问题 什么是 “symbolic reasoning ” 符号推理?



第2段

第1句

原文
However, existing work on test generation has ignored a broad class of APIs: Functions that accept another function as a callback argument and then invoke that other function asynchronously.

译文
然而,现有的测试生成工作忽略了一大类 API:接受另一个函数作为回调参数然后异步调用另一个函数的函数.

问题 :无


第2、3句

原文
The key benefit of asynchronous callbacks is that they do not block the main computation, which is useful, e.g., when accessing some kind of resource or when triggering a long-running computation.
Asynchronous callbacks have been shown to be popular [14], but also prone to mistakes and surprising behavior [28, 41].

译文
异步回调的主要好处是它们不会阻塞主计算,这很有用,例如,在访问某种资源或触发长时间运行的计算时。
异步回调已被证明很受欢迎 [14],但也容易出错和令人惊讶的行为 [28, 41]。

问题 :无


第4句

原文
While the JavaScript community has started migrating to asynchronous APIs that rely on promises [1, Section 25.6] and async/await [1, Section 25.7], a vast amount of JavaScript code still uses event-driven APIs that invoke callback functions passed to them asynchronously.

译文
虽然 JavaScript 社区已经开始迁移到依赖于 promise [1, Section 25.6] 和 async/await [1, Section 25.7] 的异步 API,但大量的JavaScript代码仍然使用事件驱动的APIs, 这些APIs调用异步传递给它们的回调函数

问题: invoke callback functions passed to them asynchronously 这句话看不懂



第3段

第1句

原文
We observe that existing test generators miss out on two opportunities for testing APIs with asynchronous callbacks.

译文
我们观察到现有的测试生成器错过了两个使用异步回调测试 API 的机会。

问题:无


第2句

原文
First, in addition to sequencing function calls, one can also consider nesting them, by placing an API call into a callback passed to another API function under test.
Such nesting enables a test to use values produced by an API that are available only once a callback has been invoked; moreover, nesting is often necessary to ensure a specific ordering of invocations to API functions.

译文
首先,除了对函数调用进行排序之外,还可以考虑嵌套它们,方法是将 API 调用放入传递给另一个被测 API 函数的回调中。
首先,除了排序函数调用之外,我们还可以考虑嵌套它们,通过将一个API调用放置到传递到另一个正在测试的API函数的回调中.
这种嵌套使测试能够使用由API产生的值,这些值只有在回调被调用时才可用;此外,嵌套通常是必要的,以确保对API函数的调用的特定顺序。

问题


Second, even the best existing test generator aimed at testing functions with callbacks [35] supports only synchronous, but not asynchronous callbacks.

第3句

原文
Second, even the best existing test generator aimed at testing functions with callbacks [35] supports only synchronous, but not asynchronous callbacks.

译文
其次,即使是现有的最好的旨在测试回调函数的测试生成器,[35]也只支持同步回调,而不支持异步回调。

问题


第4句

原文
The table below compares our work with the capabilities of two related techniques our work is inspired by:在这里插入图片描述

译文
下表将我们的工作与启发我们工作的两种相关技术的能力进行了比较:
在这里插入图片描述

问题:无


第4段

第1句

原文
To illustrate the challenges associated with testing asynchronous APIs, consider a library for accessing JSON files.

译文
为了说明与测试异步 API 相关的挑战,请考虑一个用于访问 JSON 文件的库.

问题


第2、3句

原文
The API defines a function exists for checking whether a JSON file with a specified name exists, which produces a handle to that file if this is the case.
Moreover, there is a function read for parsing a JSON file represented by a given handle.

译文
API 定义了一个函数 exists 用于检查具有指定名称的 JSON 文件是否存在,如果是,则生成该文件的句柄。
此外,还有一个函数 read 用于解析由给定句柄表示的 JSON 文件。

问题


第4句

原文
In JavaScript, functions in eventdriven APIs typically take a callback as their last argument, which is invoked with two arguments: (i) an object that indicates whether an error has occurred (or null if no error occurred) and (ii) an object representing the results of the operation. Hence, a typical use of the library would look as follows:

译文
在 JavaScript 中,事件驱动 API 中的函数通常将回调作为其最后一个参数,该参数用两个参数调用:(i)一个指示是否发生了错误的对象(如果没有发生错误则为null)和(ii)一个表示操作结果的对象。因此,该库的典型用法如下:

let fileName = ...;
exists ( fileName ,
// asynchronously invoked callback function :
(err , fileHandle ) => {
if (! err ) {
read ( fileHandle ,
// another callback function :
(err , jsonObj ) => { ... })
}
})

问题


第5段

第1、2、3句

原文
The call to read is nested in the callback that is passed to exists, to ensure that the read operation is executed after the exists operation has completed.

Now suppose that the read operation contains a bug that is triggered in certain cases where a valid file-handle is passed (e.g., if the file’s permissions do not permit read access), and suppose that we want to generate a test that invokes the read function to expose the bug.

Since file-handle objects are created inside the library, it is unclear what the representation of these objects looks like without analyzing or executing the library code.

译文
对 read调用嵌套在传递给exists的回调中,以确保read操作在exists操作完成后执行。

现在假设读操作包含一个bug,在某些情况下,当传递了一个有效的文件句柄时(例如,如果文件的权限不允许读访问)会触发这个bug,并且假设我们想要生成一个调用read函数来暴露这个错误的测试。

由于文件句柄对象是在库中创建的,所以在不分析或执行库代码的情况下,不清楚这些对象的表示是什么样子.

问题


第4、5、6句

原文
While it is possible for a test generator to create suitable file-handle objects using a purely random approach, the chances of successfully creating a valid file-handle would be small.

Therefore, the most effective way to obtain a valid file-handle and expose the bug is to invoke exists with some callback function f , and invoke read with the file-handle that is passed to f as its second argument.

That is, we would generate a test where a call to read is nested in the callback that is passed to exists, as in the above example.

译文
虽然测试生成器可以使用纯随机方法创建合适的文件句柄对象,但成功创建有效文件句柄的机会很小。

因此,获取有效的文件句柄并暴露错误的最有效方法是调用存在的回调函数f,并调用读取文件句柄,文件句柄作为它的第二个参数传递给f。

也就是说,我们将生成一个测试,其中要读取的调用嵌套在传递给exists的回调中,如上例所示。

问题


第6段

第1、2、3句

原文
Unfortunately, the state of the art test generator for testing functions with callbacks [35] is unable to generate such a test for the two reasons mentioned in the above table:

First, it fails to identify API functions that receive an asynchronously invoked callback argument, and hence, never passes callbacks into such functions.

Second, it does not construct tests where a call to one API function is nested inside the callback passed to another API function

译文
不幸的是,由于上表中提到的两个原因,用于测试带有回调的函数的最先进的测试生成器 [35] 无法生成这样的测试:

首先,它无法识别接收异步调用回调参数的 API 函数,因此永远不会将回调传递给此类函数。

其次,它不会构建对一个 API 函数的调用嵌套在传递给另一个 API 函数的回调中的测试

问题


第7段

第1、2句

原文
This paper presents Nessie, the first feedback-directed test generation technique that nests API calls into callbacks and that supports asynchronous APIs.

At the core of the approach is a novel treebased representation of test cases, which allows for growing a test case by either sequencing API calls, i.e., adding sibling nodes, or by nesting API calls, i.e., adding child nodes.

译文
本文介绍了 Nessie,这是第一个将 API 调用嵌套到回调中并支持异步 API 的反馈导向测试生成技术。
这篇论文介绍了Nessie,它是第一个反馈导向测试生成技术,它将API调用嵌套到回调中,并支持异步API。

该方法的核心是一种新颖的基于树的测试用例表示,它允许通过排序 API 调用(即添加兄弟节点)或嵌套 API 调用(即添加子节点)来扩展测试用例。

问题


第3、4句

原文
We present an algorithm for iteratively generating tree-shaped tests based on feedback from executing already generated tests.

The algorithm is supported by an automated API discovery phase that determines which API functions accept asynchronous or synchronous callbacks and by guiding the test generator toward realistic API usages based on nesting examples mined from existing API clients.

译文
我们提出了一种基于执行已生成测试的反馈迭代生成树形测试的算法。

该算法由一个自动化的 API 发现阶段支持,该阶段确定哪些 API 函数接受异步或同步回调,并根据从现有 API 客户端挖掘出的嵌套示例,引导测试生成器实现真实(实际的) API 使用。

问题



第8段 主要讲Nessis怎么优秀

第1、2句

原文
Our implementation targets JavaScript, where asynchronous callbacks are particularly prevalent and where generating effective tests is particularly challenging due to the absence of statically declared types.

Our evaluation applies Nessie to ten popular JavaScript libraries that include a total of 356 API functions, 142 of which expect callbacks.

译文
我们的实现以 JavaScript 为目标,在JavaScript中,异步回调特别普遍,并且由于缺少静态声明的类型,生成有效的测试特别具有挑战性。


我们的评估将 Nessie 应用于 10 个流行的 JavaScript 库,这些库总共包含 356 个 API 函数,其中 142 个需要回调.

问题


第3-7句

原文
Nessie’s API discovery phase detects 62% of the API signatures with callback arguments that are mentioned in the API’s documentation, and 106 undocumented API signatures with callbacks, reflecting unexpected behavior.

The coverage achieved by Nessie converges significantly more quickly than with the state of the art LambdaTester approach [35] and even reaches a slightly higher coverage: On average, Nessie needs to generate only 136 tests to achieve the same coverage that LambdaTester achieves with 1,000 generated tests.

We conjecture that this is the case because the nesting of callback functions enables a more effective selection of argument values in subsequent (nested) function calls.

We also compare the ability of Nessie and LambdaTester to detect situations where tests generated for a given version of an API behave differently when run against the next version of that API.

On average, Nessie detects 23% more behavioral differences than LambdaTester, including a mix of bugs and intentional API changes.

译文
Nessie 的 API 发现阶段检测到 62% 的 API 签名带有 API 文档中提到的回调参数,以及 106 个未记录的带有回调的 API 签名,反映了意外行为。

与最先进的 LambdaTester 方法 [35] 相比,Nessie 实现的覆盖率收敛速度明显更快,甚至达到略高的覆盖率:平均而言,Nessie 只需生成 136 个测试即可达到与 LambdaTester 生成的 1,000 个测试相同的覆盖率测试。

我们推测,之所以会出现这种情况,是因为回调函数的嵌套可以在后续(嵌套)函数调用中更有效地选择参数值。

我们还比较了Nessie和Lambda Tester的检测能力,它们能够检测到,对于给定版本的API,当运行到该API的下一个版本时,生成的测试会有不同的表现。

平均而言,Nessie 检测到的行为差异比 LambdaTester 多 23%,包括混合的bug和有意的 API 更改。

问题


第8句

原文
While these differences can, in principle, all be detected without nesting API calls, our approach finds them more effectively and efficiently due to its ability to nest calls.

译文
虽然原则上这些差异都可以在没有嵌套 API 调用的情况下检测到,但我们的方法由于它能够嵌套调用,因此能够更有效地找到它们。

问题


第9段 总结本论文的贡献

第1句

原文
In summary, this paper contributes the following:

• The first automated test generator specifically aimed at APIs that accept callbacks to be invoked asynchronously.

• An algorithm for incrementally generating tests that not only sequence API calls but also nest them inside callbacks.

• Empirical evidence demonstrating that: (i) the approach is effective at exercising JavaScript APIs with asynchronous callbacks, (ii) that it achieves modestly higher code coverage and finds more behavioral differences than the state of the art, and (iii) that it converges much more quickly than prior work when it comes to achieving a specific level of coverage or behavioral differences.

译文
总而言之,本文的贡献如下:

• 第一个自动化测试生成器,专门针对接受异步调用的回调的 API。

• 一种增量生成测试的算法,不仅可以对 API 调用进行排序,而且可以将它们嵌套在回调中。

• 经验证据表明:(i) 该方法在执行带有异步回调的 JavaScript API 方面是有效的,(ii) 与现有技术相比,它实现了更高的代码覆盖率并发现了更多的行为差异,以及 (iii) 它收敛在实现特定水平的覆盖范围或行为差异方面,比以前的工作要快得多。

问题


二、OVERVIEW OF NESSIE

第1段 概括测试生成技术

第1-3句

原文
This paper presents a test generation technique for testing higherorder functions.

A function is called a higher-order function if it expects another function to be passed as an argument, or if it returns a function.

Our work targets functions f that receive a callback function cb as an argument and then invoke the callback either synchronously or asynchronously.

Asynchronous invocation here means that the execution of f causes cb to be invoked from the main event loop at some later time.

译文
本文介绍了一种用于测试高阶函数的测试生成技术。

如果一个函数期望将另一个函数作为参数传递,或者它返回一个函数,则该函数称为高阶函数。

我们的工作目标函数 f 接收回调函数 cb 作为参数,然后以同步或异步方式调用回调 (函数)。

这里的异步调用意味着 f 的执行导致 cb 在稍后的时间从主事件循环中调用。

问题


第1句

原文
译文

问题


第2段 主要讲了 异步APIs测试的3个 挑战

第1-3 句

原文
Generating tests for asynchronous APIs involves several open challenges.

The first challenge is to find out which API functions expect (a)synchronous callbacks and at what argument positions these callbacks should be passed.

Since JavaScript is dynamically typed, our approach needs to infer the signatures of functions as a prerequisite to generating effective tests.

译文
为异步 API 生成测试涉及几个开放的挑战。

第一个挑战是找出哪些 API 函数需要(a)同步回调,以及这些回调应该在什么参数位置传递.

由于 JavaScript 是动态类型的,我们的方法需要推断函数的签名作为生成有效测试的先决条件.

问题 第一个挑战,找出、确定


第4句

原文
The second challenge is about how to compose multiple API calls into a test. While existing work focuses on sequencing calls, i.e., one call statement after another, sequencing alone is insufficient for testing asynchronous higher-order functions.

译文
第二个挑战是关于如何将多个 API 调用组合到一个测试中。虽然现有工作侧重于排序调用,即一个接一个的调用语句,但仅凭排序不足以测试异步高阶函数。

问题


第5句

原文
The third challenge is about how to compose API calls in a realistic way.
To increase the chances that our approach nests API calls in ways that represent real-world API usage, it requires some knowledge of typical API usage.

译文
第三个挑战是如何以一种现实的方式组合API调用.
为了增加我们的方法以代表真实世界API使用的方式嵌套API调用的机会,它需要一些典型API使用的知识

问题


第3段 主要讲述 为克服3个挑战而提出的解决方法。

如下图所示:
在这里插入图片描述

第1、2句

原文
Our approach, illustrated in Figure 1, consists of three main components that each address one of the challenges described above.

Given a set of API functions to test,
the first step is automated API discovery, which probes the API functions under test to determine if and where they expect callback arguments. The discovered information is stored as a set of abstract signatures, which record whether the arguments are:
(i) a synchronously invoked callback,
(ii) an asynchronously invoked callback, or
(iii) a value that is not a callback.

译文
我们的方法(如图 1 所示)由三个主要组件组成,每个组件都解决了上述挑战之一。

给定一组要测试的 API 函数,
第一步是自动化 API 发现,它探测被测 API 函数以确定它们是否以及在何处期望回调参数。发现的信息存储为一组抽象签名,记录参数是否为:
(i) 同步调用的回调,
(ii) 异步调用的回调,或
(iii) 不是回调的值。

问题


第3-6句

原文
Then, the abstract signatures discovered in this phase serve as input to a feedback-directed test generation algorithm, which is the core of the approach.

The test generation is centered around a tree-based representation of test cases, called test case trees, which the approach iteratively grows into full test cases.

To inform decisions about how API functions should be combined, the approach also mines API usage patterns in existing open-source clients of the libraries under test.

This information is passed to the test generator and used to support nesting decisions.

译文
然后,在这个阶段发现的抽象签名作为反馈导向的测试生成算法的输入,这是该方法的核心。

测试生成以测试用例的基于树的表示为中心,称为测试用例树,该方法迭代地成长为完整的测试用例。

为了决定如何组合API函数,该方法还在测试库的现有开源客户端中挖掘API使用模式。

此信息被传递给测试生成器,并用于支持嵌套决策。

问题


第7句

原文
The end product of this process is a set of test cases, which can be used in a variety of applications, e.g., regression testing.

译文
此过程的最终产品是一组测试用例,可以在各种应用程序中使用,例如,回归测试.

问题


三、API DISCOVERY(方法第一步)

第1段

第1-6句

原文
The first step in test generation is determining what to test: Given a library under test, Nessie retrieves the set of all function properties offered by the library object.

As JavaScript is a dynamically typed language, Nessie initially does not know anything about these functions beyond their names.

One possible approach to learn more about the APIs would be to rely on optional type annotations, e.g., in the form of third-party TypeScript type declarations for popular libraries.

However, not all JavaScript code comes with type annotations [25] and even if it exists, an API’s implementation may diverge from its declared type [21].

Nessie addresses this problem through an API discovery phase that probes API functions to determine at what parameter positions they expect callbacks and whether these are invoked synchronously or asynchronously.

This information is recorded as a set of abstract signatures, or simply signatures.

译文
测试生成的第一步是确定要测试什么:给定一个要测试的库,Nessie 检索库对象提供的所有函数属性的集。

由于 JavaScript 是一种动态类型语言,Nessie 最初对这些函数一无所知,只知道它们的名称。

了解更多有关 API 的一种可能方法是依赖可选的类型注释,例如,以流行库的第三方 TypeScript 类型声明的形式。

然而,并非所有 JavaScript 代码都带有类型注释 [25],即使它存在,API 的实现也可能与其声明的类型 [21] 不同。

Nessie 通过一个API 发现phase 解决了这个问题,该阶段探测 API 函数,以确定他们期望回调的参数位置,以及这些callbacks是同步调用还是异步调用。

该信息被记录为一组抽象签名,或简称为签名。

问题


第7句

原文
Definition 1 (Abstract signature).
An abstract signature for a function f is a tuple (arg1, …, argn ), where each argi is one of the following three kinds of elements:
async: an argument is an asynchronously invoked callback
sync: an argument is a synchronously invoked callback
the _ symbol: any ngon-callback argument

译文
定义 1(抽象签名)。
函数 f 的抽象签名是一个元组 (arg1, …, argn ),其中每个 argi 是以下三种元素之一:
• async:参数是异步调用的callcabk
• 同步:参数是同步调用的callback
• 符号:任何非callback参数

问题


第2段

第1、2句

原文
A single function may have zero, one, or multiple signatures.

Zero signatures indicates that the API discovery failed to find any signatures for the function, in which case the approach falls back to a default test generation strategy that does not pass any callbacks.

Multiple signatures are inferred when functions are overloaded.
For example, the outputJson function from fs-extra has two signatures: (, async) and (, _, async).
The reason is that outputJson has an optional second argument, and always takes a callback function as the last argument.

In our experience, such overloading is extremely common in JavaScript APIs due to optional arguments preceding the (final) callback argument。

译文
单个函数可能有零个、一个或多个签名。

零个签名表示 API 发现未能找到函数的任何签名,在这种情况下,该方法会退回到不传递任何callbacks的默认测试生成策略。

函数overloaded时会推断出多个签名。
例如,来自 fs-extra 的 outputJson 函数有两个签名:( _, async) 和 ( _, _, async)。
原因是 outputJson 有一个可选的第二个参数,并且总是将callback function作为最后一个参数。

根据我们的经验,由于(最终)callback argument之前的可选参数,这种overloading 在 JavaScript API 中非常常见。

问题


第3段

第1句

原文
To discover signatures for a given API function under test, Nessie repeatedly invokes the function with randomly generated arguments.

The approach alternates between generating calls with and without a callback argument, and passes different numbers of arguments.

A generated test for a function api is structured as follows:

在这里插入代码片

译文
为了发现测试中给定API函数的签名,Nessie 使用随机生成的参数反复调用该函数。

该方法在生成带回调参数和不带回调参数的调用之间交替,并传递不同数量的参数.

为一个函数 api 生成的测试结构如下:

let callback = () => { console.log(" Callback executed ");}
try {
// try calling the specified API function
api (... , callback , ...);
console.log(" API call executed ");
} catch (e) {
console.log(" Error in API call ");
}
console.log(" Test executed ");

问题


第4段

第1-3句

原文
During the execution of these tests, the print statements track if and when callbacks are invoked, and whether the function terminates successfully.

We ignore erroneous executions, as they may be due to incorrect arguments passed to the function.

For nonerroneous executions, the approach distinguishes three cases:

• a callback that executes after the test has executed is executed asynchronously, so a signature is created with async at the position of the callback argument and _ at all other positions,
• a callback that executes before the API call returns is executed synchronously, so a signature is created with sync at the callback position and _ at all other positions,
• if the callback is not executed or the test does not pass any callback, a signature with _ symbols only is created.

译文
在执行这些测试期间,打印语句会跟踪是否调用回调以及何时调用回调,以及函数是否成功终止。

我们忽略错误的执行,因为它们可能是由于传递给函数的参数不正确。
对于非错误执行,该方法区分了三种情况:

• 在测试执行后执行的回调是异步执行的,因此在回调参数的位置使用 async 创建签名,在所有其他位置使用 _ 创建签名,
• 在 API 调用返回之前执行的回调是同步执行的,因此在回调位置使用 sync 创建签名,在所有其他位置使用 _创建签名,
• 如果未执行回调或测试未通过任何回调,则仅创建带有 “_符号” 的签名。

问题


### 第4-6句

原文
We test with a single callback argument at a time, i.e., our approach will not discover signatures with multiple callback arguments.

The rationale is that API functions with multiple callbacks are relatively rare.
Extending the algorithm to support multiple callbacks is straightforward but increases the computational complexity of API discovery.

In general, the results of the API discovery phase are unsound, because the approach does not guarantee to cover all possible arguments or all paths through the API implementation

译文
我们一次使用一个回调参数进行测试,也就是说,我们的方法不会发现具有多个回调参数的签名。

理由是具有多个回调的 API 函数相对较少。
扩展该算法以支持多个回调很简单,但会增加 API 发现的计算复杂度。

一般来说,API discovery phase的结果并不可靠,因为该方法不能保证覆盖所有可能的参数或通过 API 实现的所有路径。

问题


第5段 最后一段。

第1、2句

原文
The output of the API discovery is the set of discovered signatures for each function offered by the library under test.

When generating tests, the number of arguments and callback positions (if the function has any) used during test generation are informed by these discovered signatures.

译文
API 发现的输出是被测库提供的每个函数的已发现签名集。

在生成测试时,在测试生成期间使用的参数和回调位置(如果函数有的话)的数量由这些发现的签名通知。

问题 讲述了 API discovery发现的啥。discovery的输出是签名集。



四、FEEDBACK-DIRECTED TEST GENERATION(方法核心)

第1句

原文
The following describes the core algorithm of Nessie, which generates tests cases that both sequence and nest API calls. The algorithm is based on a tree-shaped representation of test cases called a test case tree (Section 4.1), which serves as the basis for the algorithm itself (Section 4.2).

译文
下面介绍 Nessie 的核心算法,该算法生成测试用例,同时对 API 调用进行排序和嵌套。该算法基于一个称为测试用例树(第 4.1 节)的树形表示,它作为算法本身的基础(第 4.2 节)。

问题


4.1 Test Case Trees (核心方法第一步)

第1段

第1句

原文
To represent test cases that support both sequencing and nesting of method calls, we define the text case tree, a novel intermediate representation of test cases:

译文
为了表示同时支持方法调用的顺序和嵌套的测试用例,我们定义了文本用例树,这是测试用例的一种新的中间表示:

问题


第2句

原文
Definition 2 (Test case tree).

Let V be a map of variable names to non-callback values, called value pool, and S a map of function names to abstract signatures. Then, a test case tree is an ordered tree where nodes are either:


• a call node of the form r = api (a1, …, ak ), meaning that function api is invoked with arguments (a1, …, ak ) and yields return value r . If si ∈ {sync, async} for some signature (api → (s1, …, sn )) ∈ S, then ai may be a callback function. Otherwise, ai ∈ V or it is a return value of another call, or
• a callback node of the form cb(p1, …,pk ), meaning that callback function cb receives parameters p1, …,pk .


Edges are either:
• a contains edge from a callback node to a call node, meaning that there is a call in the body of the callback function, or
• an argument edge from a call node to a callback node, meaning that a call is given a callback function as an argument.

译文
定义 2(测试用例树
设 V 是变量名到非回调值的映射,称为值池,S 是函数名到抽象签名的映射。然后,一个测试用例树是一个有序树,其中节点是:
• r = api (a1, …, ak ) 形式的调用节点,这意味着函数API被调用时带有参数(a1,…, ak),并产生返回值 r 。如果 si ∈ {sync, async} 对于某个签名 (api 7→ (s1, …, sn )) ∈ S,那么 ai 可能是一个回调函数。否则,ai ∈ V 或者它是另一个调用的返回值,或者
• 一个形式为cb(p1,…,pk)的回调节点,表示回调函数cb 接收参数p1, …,pk 。
边缘是:
• 一个包含从回调节点到调用节点的边,这意味着回调函数的主体中有一个调用,或者
• 一个从调用节点到回调节点的参数边,这意味着一个调用将被赋予一个回调函数作为参数。

问题


第2段

第1句

原文
The root node of a test case tree is a special callback node that corresponds to the function that contains the entire test case. The order of the call nodes under a callback node represents the sequential order in which calls occur in the body of a callback function.

译文
测试用例树的根节点是一个特殊的回调节点,对应于包含整个测试用例的函数。回调节点下的调用节点的顺序表示回调函数体中调用发生的顺序。

问题


## 第3段 为上一段举一个例子解释。

原文
Example.

Figure 2 gives an example of a test case and its corresponding test case tree.
Each API call in the test case in Figure 2a is represented by a call node in the test case tree of Figure 2b.
The nodes for calls that receive callback arguments each have a corresponding callback node as a child.

E.g., the callback given to ensureFile at line 11 is represented by the callback node callback(a, b, c, d, e). Calls nested within the body of a callback function are represented as children of callback nodes.

E.g., the call to readJson on line 12 corresponds to the lower-left call node of the tree. The value pool of the test consists of two entries, which map the variable names to their respectively assigned values in lines 8 to 9.

在这里插入图片描述

译文

例子。
图 2 给出了一个测试用例及其对应的测试用例树的示例。
图 2a 中的测试用例中的每个 API 调用都由图 2b 的测试用例树中的调用节点表示。
接收回调参数的调用节点每个都有一个对应的回调节点作为子节点。

例如,第 11 行提供给 ensureFile 的回调由回调节点 callback(a, b, c, d, e) 表示。嵌套在回调函数主体中的调用表示为回调节点的子节点。

例如,第 12 行对 readJson 的调用对应于树的左下角调用节点。测试的值池由两个条目组成,它们将变量名称映射到它们在第 8 到 9 行中分别分配的值。

第4段 主要是引出新一个“Definition 3”

part 1

原文
A call in a test case can use as arguments only values that are available at the call site according to the scoping rules of JavaScript.

We say that a test case is well-formed if, for all calls, its arguments are bound to some declaration when the call is reached during the execution of the test case.

Given our tree representation of a test case, a test case is well-formed if and only if the following holds:

译文
根据 JavaScript 的范围规则,测试用例中的调用只能将调用站点可用的值用作参数。

如果在执行测试用例期间到达调用时,对于所有调用,它的参数都绑定到某个声明,则我们说测试用例是格式良好的。

鉴于我们对测试用例的树表示,当且仅当满足以下条件时,测试用例是格式良好的:

part 2

原文
Definition 3 (Well-formedness).
In a well-formed test case tree, each argument of a call node n is one of the following:

• A random primitive value, inserted by referring to one of the entries in the value pool V .
• A random object value (array literal, object literal, or function), also inserted by referring to one of the entries in V .
• The return value r of a call node n′ that is a left sibling of n or a left sibling of any ancestor call node of n (these represent return values of calls executed before reaching the call in n).
• A parameter pi of a callback node on the path between the root node and n (these represent formal parameters of a surrounding callback function).
• A callback function cbx , where n has a callback node that represents cbx as a child.

译文:
定义 3(格式良好)。
在格式良好的测试用例树中,调用节点 n 的每个参数都是以下之一:

• 一个随机原始值,通过引用值池V中的某一项来插入。
• 一个随机对象值(数组字面量、对象字面量或函数),也通过引用 V 中的一个条目来插入的。
• 作为n 的左兄弟或n 的任何祖先调用节点的左兄弟的调用节点n’ 的返回值r(这些表示在到达n 中的调用之前执行的调用的返回值)。
• 在根节点和n之间的路径上的回调节点的参数pi(这些代表周围回调函数的形式参数)。
• 回调函数 cbx ,其中 n 有一个回调节点,它将 cbx 表示为子节点。

第5段 接着上个“Definition 3”,举一个例子。

原文
Example.
Figure 2b shows a test case tree where all arguments are well-defined.

E.g., in the call of ensureFile, the first argument is arg590, which is a randomly generated primitive value in the value pool (a string literal, defined on line 8),
and the second argument is a callback node.

In contrast, the call of stat could not use, e.g., a as an argument because a is not in the parameter list of any callback node on the path between stat’s node and the root node.

在这里插入图片描述

译文
例子。
图 2b 显示了一个测试用例树,其中所有参数都定义良好。

例如,在 ensureFile 的调用中,第一个参数是 arg590,它是值池中随机生成的原始值(字符串字面量,在第 8 行定义),
第二个参数是回调节点。

相反,stat 的调用不能使用例如 a 作为参数,因为 a 不在 stat 节点和根节点之间的路径上的任何回调节点的参数列表中。

问题


4.2 Test Generation Algorithm (核心方法第二步)

第一段

原文
Our algorithm creates test cases iteratively, by repeatedly extending an existing test case with another call at extension points, which represent locations in a given test case where a new call node could be inserted.

Given a test case tree, there is an extension point for each callback node that is executed during test execution, which adds another child node to the already existing child nodes, at the right-most position.

For callback nodes with no children, there is an extension point for adding a first child node.

我们的算法迭代地创建测试用例,通过在扩展点用另一个调用重复扩展现有测试用例,这些扩展点表示给定测试用例中可以插入新调用节点的位置。

给定一个测试用例树,在测试执行期间执行的每个回调节点都有一个扩展点,它在最右边的位置向已经存在的子节点添加另一个子节点。

对于没有子节点的回调节点,有一个用于添加第一个子节点的扩展点。

第二段 为上一段的定义,举了一个例子,还是图2.

Example.

Figure 2b shows the extension points of the test case tree, as well as edges that would be added if the test is extended at these points (labeled the extension edges).

These extension points correspond to adding a call right after lines 12 and 16 in Figure 2a.

例子。

图 2b 显示了测试用例树的扩展点,以及如果在这些点上扩展测试将添加的边(标记为扩展边)。

这些扩展点对应于在图 2a 中的第 12 行和第 16 行之后添加一个调用。

第三段 开始讲述我们的算法:反馈导向方法。

原文
Algorithm 1 summarizes our feedback-directed approach for creating test cases.

It maintains a set T of generated tests and a set E of extension points.

Each extension point is a pair (t ,n) of a test case tree t and a node n in this tree, representing the callback node where a new call node could be inserted.

The main loop extends an existing test with a new call at one of the extension points and adds the test to T .

The extended test t ′ is then executed to gather feedback about its execution.

If no exception is thrown, each possible callback node that is executed is kept as a possible extension point to create a further test.

The algorithm relies on helper functions for choosing a function to call, choosing arguments to pass into the function, and identifying future extension points, which we describe below.

在这里插入图片描述

译文
算法 1 总结了我们创建测试用例的反馈导向方法。

它维护了一组生成的测试T 和一组扩展点E。

每个扩展点是一对(t,n)测试用例树t和该树中的一个节点n,表示可以插入一个新的调用节点的回调节点.

主循环在一个扩展点上用一个新的调用扩展现有测试,并将测试添加到 T 。

然后执行扩展测试t’以收集有关其执行的反馈。

如果没有抛出异常,则将执行的每个可能的回调节点保留为可能的扩展点,以创建进一步的测试.

该算法依赖于辅助函数来选择要调用的函数,选择要传递给函数的参数,以及识别未来的扩展点,我们将在下面进行描述。

第4段,紧接上一段,选择一个“辅助函数”来完成该算法。

Choosing a function to call.
Given a specific extension point, Algorithm 1 calls chooseFunction to pick a function to call by balancing two requirements.

On the one hand, the generated tests should cover as many functions as possible.
On the other hand, we do not want to prescribe a specific order in which functions are selected.

To this end, the approach assigns to each of the given functions a weight and then takes a weighted, random decision.

Initially, all functions have uniformly distributed weights.
When a function is selected by chooseFunction, its weight is divided by a constant factor (four in our current implementation).

Note that this reduction is done every time a function is chosen, i.e., if the same function is chosen twice, its weight is divided by the constant factor twice.

In addition to the above, chooseFunction is guided by a mined model of nested API functions, as explained in detail in Section 4.3

选择要调用的函数。
给定一个特定的扩展点,算法 1 调用 chooseFunction 通过平衡两个要求来选择要调用的函数。

一方面,生成的测试应该涵盖尽可能多的功能。
另一方面,我们不想规定选择功能的特定顺序。

为此,该方法为每个给定函数分配一个权重,然后采取加权的随机决策。

最初,所有函数都具有均匀分布的权重。
当一个函数被chooseFunction选中时,它的权重除以一个常数因子(在我们当前的实现中是4)。

请注意,每次选择一个函数时都会进行此缩减,也就是说,如果同一个函数被选择了两次,那么它的权重将被两次除以常数因子。

除了上述之外,chooseFunction 是由一个挖掘的嵌套API函数模型来指导的,如第 4.3 节中详细说明的那样

第5段,与上一段并列,主要是“选择要传递给函数的参数”

Choosing arguments to pass into a function.
Once a function has been selected for testing, arguments need to be generated for it.

This is done by consulting the list of signatures produced by the discovery phase.
If multiple signatures exist for a function, one is chosen at random.

The signatures inform the test generation of the number of arguments that the function should be passed, and which (if any) are callback arguments.
If no signatures exist for the function, a random number of arguments is selected (between 0 and 5), and arguments are generated randomly to fill these positions.

Note that, in these cases, no callback arguments are generated.

选择要传递给函数的参数。
一旦选择了一个函数进行测试,就需要为其生成参数。

这是通过查询发现阶段产生的签名列表来完成的。
如果一个函数存在多个签名,则随机选择一个。

签名通知测试生成函数应该传递的参数数量,以及哪些(如果有)是回调参数。
如果函数不存在签名,则选择一个随机数量的参数(介于 0 和 5 之间),并随机生成参数来填充这些位置。

请注意,在这些情况下,不会生成回调参数。

第6段 对上一段的情况,举出一些特例。

For non-callback arguments, the type is selected randomly from the JavaScript primitive types (number, string, and boolean), object literals, arrays, functions, and other.

If the selected type is any of the primitives, object, or array, then randomly generated values of this type are used.

If the selected type is function, an available function is chosen from the API under test or the runtime environment (e.g., console.log).

If the selected type is other, a variable that is available at the current scope is selected, which includes return values from previous API calls and arguments to previous callbacks in the test case tree (Definition 3).

对于非回调参数,类型是从 JavaScript 原始类型(数字、字符串和布尔值)、对象字面量、数组、函数等中随机选择的。

如果选择的类型是基元、对象或数组中的任何一个,则使用此类型的随机生成的值。

如果选择的类型是函数,则从被测 API 或运行时环境(例如,console.log)中选择一个可用的函数。

如果选择的类型是其他,则选择在当前范围内可用的变量,其中包括来自先前 API 调用的返回值和测试用例树中先前回调的参数(Definition 3)。

第7段 不知道说的啥意思

Nesting API calls helps with generating well-formed arguments, as values (including objects) may get passed from outer to inner calls, as illustrated in the motivating example in Section 1.

In addition, since we are working with many file system-related libraries, string primitive values are selected randomly from a pre-made list of valid file names that correspond to a small hierarchy of directories and files generated during the setup of Nessie for the purposes of the testing.

Beyond these two points, we do not address the problem of generating complex objects in this work.

嵌套 API 调用有助于生成语法正确的参数,因为值(包括对象)可以从外部调用传递到内部调用,如第 1 节中的激励示例所示。

此外,由于我们正在使用许多与文件系统相关的库,因此字符串原始值是从预先制作的有效文件名列表中随机选择的,这些文件名对应于在设置Nessie过程中生成的目录和文件的小层次结构。

除了这两点之外,我们没有解决在这项工作中生成复杂对象的问题。

第8段 添加新的扩展点

Adding new extension points.
After executing a generated test, extensionPoints is called to identify where to extend the test in future iterations.

This function returns an extension point for each callback node that has been executed, corresponding to the insertion of a new child node to the right of its existing children (see Figure 2b).

There are two reasons for not adding an extension point: exceptions thrown by the tested APIs and callback functions that are never invoked.

By examining feedback from test executions, the algorithm avoids creating future tests that build on code that will never execute.

A single test may have multiple extension points because more than one of its callbacks may execute.

Note that extension points are not removed after being used, so the set of extension points grows monotonically, enabling for multiple new tests to be derived from an extension point in a single base test.

添加新的扩展点。
执行生成的测试后,调用extensionPoints 来确定在未来迭代中扩展测试的位置。

该函数为每个已执行的回调节点返回一个扩展点,对应于在其现有子节点右侧插入一个新子节点(参见图 2b)。
在这里插入图片描述

不添加扩展点的原因有两个:被测试的API抛出的异常和从未调用过的回调函数。

通过检查测试执行的反馈,该算法避免了在永远不会执行的代码基础上创建未来的测试。

单个测试可能有多个扩展点,因为它可能会执行多个回调。

请注意,扩展点在使用后不会被删除,因此扩展点集合单调增长,从而可以在单个基础测试中的扩展点派生出多个新测试。

小结

4.2 节 该算法主要依赖一个 “helper functions”,用来:
1、选择一个辅助函数 Choosing a function to call.
2、选择要传递给函数的参数 Choosing arguments to pass into a function
3、添加新的扩展点 Adding new extension points.

4.3 Mining API Usages

第1段 引子

Having an API call nested in the callback argument of another API call implies a relationship between these calls.

We define a notion of a nesting example to formalize such relationships.

将一个API调用嵌套在另一个API调用的回调参数中,这意味着这些调用之间存在关系。。

我们定义了一个嵌套示例的概念来形式化这种关系。

第2段 又一个定义 “ Definition 4”

Definition 4 (Nesting example). A nesting example is tuple

( $ f_ {outer} $ ,( $ arg_ {1}^ {outer} $ , $ \cdots $ , $ arg_ {m}^ {outer} $ ), $ f_ {inner} $ ,( $ arg_ {1}^ {inner} $ , $ arg_ {n}^ {inner} $))

where:
• $ f_ {outer} $ is the name of a called API function,

• every $ arg_ {i}^ {outer} $ is either $ cb_ {sync} $ or $ cb_ {async} $ (i.e., a sync or async callback argument) or _ (any non-callback argument),

• $ f_ {inner} $ is the name of an API function invoked in the callback given to $ f_ {outer} $ , and

• every $ arg_ {i}^ {inner} $ j is either o u t e r @ k outer@k outer@k (i.e., the same argument as given to $ f_ {outer} $ at position k k k), c b @ k cb@k cb@k (i.e., the k k kth parameter of the callback function), or _ (i.e., any other argument).


E x a m p l e 4.1. Example 4.1. Example4.1. The following nesting example can be mined from Figure 2a: ( e n s u r e F i l e ensureFile ensureFile, (_, , $ cb {sync} $ ), r e a d J s o n readJson readJson, ( o u t e r @ 0 ) (outer@0) (outer@0)).

$Example 4.2. $ The following usage of the $fs-extra $ API, where the o b j obj obj parameter of the callback passed to r e a d J s o n readJson readJson serves as an argument in a nested call to o u t p u t J s o n outputJson outputJson:

定义 4(嵌套示例)。嵌套示例是元组

( $ f_ {outer} $ ,( $ arg_ {1}^ {outer} $ , $ \cdots $ , $ arg_ {m}^ {outer} $ ), $ f_ {inner} $ ,( $ arg_ {1}^ {inner} $ , $ arg_ {n}^ {inner} $))

在哪里:
• $ f_ {outer} $ 是调用的 API 函数的名称,

• 每个 $ arg_ {i}^ {outer} $ 要么是 $ cb_ {sync} $ 要么是 $ cb_ {async} $(即同步或异步回调参数)或 (任何非回调参数),

• $ f_ {inner} $是回调中调用的 API 函数的名称给 $ f_ {outer} $ ,和

• 每个 $ arg_ {i}^ {inner} $ j 要么是 o u t e r @ k outer@k outer@k(即,与 $f_ {outer} $ 在位置 k k k 的参数相同),$cb@k $(即,回调函数的第 k k k 个参数)或(即,任何其他参数)。


示 例 4.1. 示例 4.1. 4.1. 下面的嵌套示例可以从图 2a 中挖掘出来:( e n s u r e F i l e ensureFile ensureFile, ( —, —, $ cb_ {async} $), r e a d J s o n readJson readJson, ( o u t e r @ 0 ) (outer@0) (outer@0)) .

$示例4.2。 $ $fs–extra $ API 的以下用法,其中传递给 r e a d J s o n readJson readJson 的回调的 o b j obj obj 参数用作对 o u t p u t J s o n outputJson outputJson 的嵌套调用中的参数:

17 // read the contents of file . json and output it to output.json
18 readJson (" file . json ", function callback (err , obj) {
19 outputJson (" output . json ", obj );
20 });

对应于:( r e a d J s o n readJson readJson, (—,$ cb_ {async} $), o u t p u t J s o n outputJson outputJson, (cb@1, _))。

第3段

We developed a static analysis for mining nesting examples from real-world uses of APIs by traversing the ASTs of existing API clients.

This analysis was implemented in CodeQL [15], using its extensive facilities for static analysis.

In particular, we use CodeQL’s access path tracking to identify functions as originating from an API import, and its single static assignment representation of local variables to identify situations where the same argument is used in an outer call and an inner call.

For shared arguments that are primitive values (e.g., the same string passed to both inner and outer calls) the relationship is identified by checking for value equality.

我们开发了一种静态分析,通过遍历现有 API clients的 ASTs,从 API 的实际使用中挖掘嵌套示例。

该分析是在 CodeQL [15] 中实现的,使用其广泛的静态分析工具。

特别是,我们使用 CodeQL 的访问路径跟踪来识别源自 API 导入的函数,并使用其局部变量的单一静态赋值表示来识别在外部调用和内部调用中使用相同参数的情况。

对于原始值的共享参数(例如,传递给内部和外部调用的相同字符串),可以通过检查值是否相等来确定关系。

第4段

The test generator uses the set of mined nesting examples in chooseFunction.

When selecting a function to be nested in the callback of some function f f f , the set of nesting examples is consulted to find examples where fouter matches f f f .

If such nesting examples exist, then one of the corresponding$ f_ {inner} $ functions is randomly selected to be invoked inside f ’ s f ’s fs callback.

Similarly, chooseArgument consults the selected nesting example to determine which arguments (if any) to reuse from the outer function or from the surrounding callback, and at what position(s).

测试生成器使用chooseFunction 中挖掘的嵌套示例集。

当在函数 f f f的回调函数中选择一个嵌套函数时,会参考嵌套示例集来查找$ f_ {outer} $匹配 f f f的示例

如果存在这样的嵌套示例, 那么将随机选择一个相应的$ f_ {inner} $ 函数在 f f f的回调中调用。

类似地,chooseArgument 参考选定的嵌套示例来确定哪些参数(如果有的话)要从外部函数或周围的回调中重新使用,以及在什么位置。

第5段

If no relevant mined nesting examples are available, an inner function is randomly selected.

The test generator is configured to only use mined data 50% of the time.

If we only used nestings that showed up in mined data, this would exclude many potentially correct pairs that simply do not occur in the mined projects.

Section 5 explores the effect of varying how often mined data is consulted on the coverage achieved by the tests.

如果没有相关的挖掘嵌套示例可用,则随机选择一个内部函数。

测试生成器被配置为只有 50% 的时间使用已挖掘的数据。

如果我们只使用出现在挖掘数据中的嵌套,这将排除许多在挖掘项目中根本不会出现的潜在正确对。

第5节探讨了不同频率的挖掘数据对测试覆盖率的影响。

五、 EVALUATION

第2句

原文
译文

问题


第1句

原文

译文

问题


继铭的总结:

Nessie是一款测试用例生成器,针对存在异步回调函数的JavaScript API进行测试。

之前的测试用例生成方法没有考虑到API的参数可能是回调函数的情况,并且生成的测试用例大多按顺序调用不同的API,没有考虑到异步的情况。

为了测试存在异步回调函数的API,
Nessie首先使用模糊测试的方法探索待测API所有可能的函数参数类型,形成API的抽象签名;
其次,利用静态分析方法分析现有的开源项目中不同API之间的嵌套调用关系;
之后定义了一种测试用例的树型表示,这种树型表示能够描述测试用例中包括回调函数在内的函数调用关系,Nessie根据之前得到的API抽象签名和API嵌套调用关系,在树型表示上进行扩展,即不断在回调函数中调用新的API,传入新的回调函数作为参数,使得生成的测试用例能够测试带有异步回调函数的API。



该方法在探索API的函数签名时,仅考虑了参数中存在一个回调函数的情况,忽略了API可能调用多个回调函数的情况,这使得生成的测试用例无法有效测试存在多个回调函数参数的API。

此外,该方法在生成测试用例的过程中不断地在树型表示上添加新的函数调用,随着时间的推移,生成的测试用例会越来越复杂,API的嵌套层数越来越多。

该方法缺少一种测试用例化简的机制,这会使得后面人工分析差异行为或者定位缺陷的过程变得困难。

11 let r_126_0 = fs_extra . ensureFile (arg590 , cb(a, b, c, d, e) =>
{
12 let r_126_0_0 = fs_extra . readJson ( arg590 );
13 return false ;
14 }

);
15
16 let r_126_1 = fs_extra . stat ( arg593 );

• RQ4:根据挖掘的嵌套示例改变选择嵌套函数对的机会有什么影响?
The API usage mining component of Nessie informs the choice of which inner API function to call when nesting API functions. By default, the mined nesting examples are consulted 50% of the time.

The following measures the effect of varying this percentage on the coverage achieved by the generated tests. The experimental setup is as in RQ2, but we consider the test generation to follow mined nesting examples 0%, 25%, 50%, 75%, and 100% of the time.

Table 6 summarizes the result of this experiment by showing the final coverage after generating 1,000 tests. The corresponding coverage plots are in the supplementary material. The table’s first row reads as follows: For fs-extra, the statement coverage when using 0% mined nestings is 32.2%, when using 25% mined nestings it is 33.6%, when using 50% mined nestings it is 37.2%, when using 75% mined nestings it is 33.0%, and when using 100% mined nestings it is 33.0%. For readability, we show the highest coverage for each project in bold.

The results illustrate the value of using mined nesting examples: 50% mined nestings always leads to a coverage that is higher than or at least as high as 0% and 100% mined nesting. This supports our initial hypothesis that choosing informed nestings is more likely to produce valid tests that will increase coverage. However, choosing only mined nestings, i.e, 100%, risks to miss valid nestings that are simply never seen during the API usage mining.

CONCLUSION

Effective test generation for APIs that make use of asynchronous
callback arguments is challenging, as the test generator must generate
tests that combine multiple calls to related API functions in
meaningful ways. Generating only sequences of calls, as done in
existing test generators, is inadequate, as it is difficult for such an
approach to produce suitable values to invoke API functions with.
We presented Nessie, the first test generator aimed at APIs with
asynchronous callbacks, which relies on both sequencing and nesting
API calls to produce suitable values to invoke API functions
with. Here, nesting here means generated tests may contain API
calls inside the body of callbacks passed to other API calls. In an
empirical evaluation, Nessie is applied to ten popular JavaScript
libraries containing 142 API functions with callbacks, and its effectiveness
is compared to that of LambaTester, a state of the art test
generation technique that creates tests only by sequencing method
calls. Our results show that Nessie finds more behavioral differences
and achieves slightly higher coverage than LambdaTester. Notably,
it needs to generate significantly fewer tests to achieve and exceed
the coverage achieved by LambdaTester.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值