-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestCaseGen.tex
executable file
·47 lines (32 loc) · 5.82 KB
/
testCaseGen.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
\subsection{Extracting DOM and \javascript Function States}
\label{Sec:testCaseGen}
In the second step, our technique extracts sequences of events from the inferred state-flow graph. These sequences of events are used in our test case generation process.
\headbf{DOM-level event-based testing} To verify the behaviour of the application at the user interface level, each event path, taken from the initial state (\code{Index}) to a leaf node in the state-flow graph, is used to generate DOM event-based test cases.
Each extracted path is converted into a \junit \selenium-based test case, which executes the sequence of events, starting from the initial DOM state.
Going back to our running example, one possible event sequence to generate is: \code{\$(`\#cell0').click$\rightarrow$\$(`div \#divElem').click$\rightarrow$\$(`\#st\-artCell').click}.
To collect the required trace data, we capture all DOM elements and their attributes after each event in the test path is fired. This trace is later used in our DOM oracle comparison, as explained in \secref{oracleGen}.
\headbf{Extracting \javascript function states} To generate unit tests that target \javascript functions directly (as opposed to event-triggered function executions), we log the state of each function at their entry and exit point, during execution.
To that end, we instrument the code to trace various entities.
At the entry point of a given \javascript function we collect (1) function parameters including passed variables, objects, functions, and DOM elements, (2) global variables used in the function, and (3) the current DOM structure just before the function is executed. At the exit point of the \javascript function and before every \code{return} statement, we log the state of the (1) return value of the function, (2) global variables that have been accessed in that function, and (3) DOM elements accessed (read/written) in the function.
At each of the above points, our instrumentation records the name, runtime type, and actual values.
The dynamic type is stored because \javascript is a dynamically typed language, meaning that the variable types cannot be determined statically.
Note that complex \javascript objects can contain circular or multiple references (e.g., in JSON format). To handle such cases, we perform a de-serialization process in which we replace such references by an object in the form
of ${\$ref: Path}$, where $Path$ denotes a $JSONPath$ string\curl{http://goessner.net/articles/JsonPath/} that indicates the target path of the reference.
In addition to function entry and exit points, we log information required for calling the function from the generated test cases.
\javascript functions that are accessible in the public scope are mainly defined in (1) the global scope directly (e.g., \code{function f()\{...\}}), (2) variable assignments in the global scope (e.g., \code{var f = function()\{...\}}), (3) constructor functions (e.g, \code{function constructor() \{this.\ member= function()\{...\}\}}), and (4) prototypes (e.g., \code{Con\-structor.prototype.f= function() \{...\}}).
Functions in the first and second case are easy to call from test cases. For the third case, the constructor function is called via the \code{new} operator to create an object type, which can be used to access the object's properties
(e.g., \code{container=new Constructor(); container.member();}).
This allows us to access the inner function, which is a member of the \code{constructor} function in the above example.
For the prototype case, the function can be invoked through \code{container.f()} from a test case.
Going back to our running example in \figref{funcCovgExample}, at the entry point of \code{setDim}, we log the value and type of both the input parameter \code{dimension} and global variable \code{currentDim}, which is accessed in the function. Similarly, at the exit point, we log the values and types of the returned variable \code{dim} and \code{currentDim}.
In addition to the values logged above, we need to capture the DOM state for functions that interact with the DOM. This is to address the fourth challenge outlined in \secref{motivation}.
To mitigate this problem, we capture the state of the DOM just before the function starts its execution, and include that as a \emph{test fixture} \cite{quint} in the generated unit test case.
In the running example, at the entry point of \code{setDim}, we log the \code{innerHTML} of the current DOM as the function contains several calls to the DOM, e.g., retrieving the element with ID \code{endCell} in Line 22. We further include in our execution trace the way DOM elements and their attributes are modified by the \javascript function at runtime.
The information that we log for accessed DOM elements includes the ID attribute, the XPath position of the element on the DOM tree, and all the modified attributes. Collecting this information is essential for oracle generation in the next step.
We use a set to keep the information about DOM modifications, so that we can record the latest changes to a DOM element without any duplication within the function.
For instance, we record ID as well as both \code{width} and \code{height} properties of the \code{endCell} element.
Once our instrumentation is carried out, we run the generated event sequences obtained from the state-flow graph. This way, we produce an execution trace that contains:
\begin{itemize}%[noitemsep]
\item Information required for preparing the environment for each function to be executed in a test case, including its input parameters, used global variables, and the DOM tree in a state that is expected by the function;
\item Necessary entities that need to be assessed after the function is executed, including the function's output as well as the touched DOM elements and their attributes (The actual assessment process is explained in \secref{oracleGen}).
\end{itemize}