Efficient Mutation Killers in Action

Similar documents
Killing strategies for model-based mutation testing

UML in Action: A Two-Layered Interpretation for Testing

Integrating Model-Based Testing and Analysis Tools via Test Case Exchange

Towards Fault-based Generation of Test Cases for Dependable Embedded Software

Towards Generation of Adaptive Test Cases from Partial Models of Determinized Timed Automata

Model-Based Mutation Testing of Reactive Systems

Model-Based Mutation Testing of an Industrial Measurement Device

Software Testing IV. Prof. Dr. Holger Schlingloff. Humboldt-Universität zu Berlin

UML in Action. A Two-Layered Interpretation for Testing. Bernhard K. Aichernig Joint work with Harald Brandl, Elisabeth Jöbstl, Willibald Krenn

Fault-based Conformance Testing in Practice

Managing test suites for services

DIVERSITY TG Automatic Test Case Generation from Matlab/Simulink models. Diane Bahrami, Alain Faivre, Arnault Lapitre

ExMAn: A Generic and Customizable Framework for Experimental Mutation Analysis 1

Test-Case Generation and Coverage Analysis for Nondeterministic Systems Using Model-Checkers

Part I: Preliminaries 24

The Encoding Complexity of Network Coding

A Formalization of Transition P Systems

Specifying Precise Use Cases with Use Case Charts

Towards Compositional Testing of Real-Time Systems

CS2 Language Processing note 3

Cover Page. The handle holds various files of this Leiden University dissertation

DISCRETE-event dynamic systems (DEDS) are dynamic

Automatic synthesis of switching controllers for linear hybrid systems: Reachability control

Monitoring Interfaces for Faults

Turn Indicator Model Overview

2386 IEEE TRANSACTIONS ON INFORMATION THEORY, VOL. 52, NO. 6, JUNE 2006

Modeling Interactions of Web Software

PROPAGATION-BASED CONSTRAINT SOLVER IN IMS Igor Ol. Blynov Kherson State University

Directed Model Checking for PROMELA with Relaxation-Based Distance Functions

Handout 9: Imperative Programs and State

On the Eects of UML Modeling Styles in Model-based Mutation Testing

Security for Multithreaded Programs under Cooperative Scheduling

How useful is the UML profile SPT without Semantics? 1

Utilizing Static Analysis for Programmable Logic Controllers

Formal Verification for safety critical requirements From Unit-Test to HIL

Issues on Decentralized Consistency Checking of Multi-lateral Collaborations

Protocol Conformance Testing a SIP Registrar: an Industrial Application of Formal Methods

Byzantine Consensus in Directed Graphs

Promela and SPIN. Mads Dam Dept. Microelectronics and Information Technology Royal Institute of Technology, KTH. Promela and SPIN

Experiments on the Test Case Length in Specification Based Test Case Generation

Test Automation. 20 December 2017

Mutant Minimization for Model-Checker Based Test-Case Generation

Category Theory in Ontology Research: Concrete Gain from an Abstract Approach

3.4 Deduction and Evaluation: Tools Conditional-Equational Logic

6.001 Notes: Section 15.1

Model Checking of Statecharts using Automatic White Box Test Generation

Implementation of Lexical Analysis. Lecture 4

Chapter S:II. II. Search Space Representation

A Test Case Generation Algorithm for Real-Time Systems

Distributed Systems Programming (F21DS1) Formal Verification

Composability Test of BOM based models using Petri Nets

ISO Compliant Automatic Requirements-Based Testing for TargetLink

Job-shop scheduling with limited capacity buffers

1 Introduction. 3 Syntax

CS 6110 S11 Lecture 25 Typed λ-calculus 6 April 2011

Introduction to Dynamic Analysis

UML2SAN: TOWARD A NEW SOFTWARE PERFORMANCE ENGINEERING APPROACH

ISO compliant verification of functional requirements in the model-based software development process

A Typed Lambda Calculus for Input Sanitation

LECTURES 3 and 4: Flows and Matchings

Introduction to Software Testing Chapter 5.1 Syntax-based Testing

Models in Conflict Towards a Semantically Enhanced Version Control System for Models

A Transformation-based Approach to Testing Concurrent Programs using UML Activity Diagrams

Proof Pearl: The Termination Analysis of Terminator

On Meaning Preservation of a Calculus of Records

Modeling, Testing and Executing Reo Connectors with the. Reo, Eclipse Coordination Tools

Object Oriented Mutation Applied in Java Application programming Interface and C++ Classes

AUTOMATED GUI TESTING OF SOFTWARE APPLICATIONS USING UML MODELS

Test Cases Generation from UML Activity Diagrams

Extracting the Range of cps from Affine Typing

Trees. 3. (Minimally Connected) G is connected and deleting any of its edges gives rise to a disconnected graph.

An Efficient Algorithm for Computing Non-overlapping Inversion and Transposition Distance

A New Method to Index and Query Sets

Unlabeled equivalence for matroids representable over finite fields

Testing! Prof. Leon Osterweil! CS 520/620! Spring 2013!

CLAN: A Tool for Contract Analysis and Conflict Discovery

5 The Control Structure Diagram (CSD)

Fault Detection of Reachability Testing with Game Theoretic Approach

Implementation of Lexical Analysis

Administrivia. Lexical Analysis. Lecture 2-4. Outline. The Structure of a Compiler. Informal sketch of lexical analysis. Issues in lexical analysis

Introduction to Formal Methods

A Survey on Different Approaches for Efficient Mutation Testing

Separating Product Variance and Domain Concepts in the Specification of Software Product Lines

want turn==me wait req2==0

Fork Sequential Consistency is Blocking

Line Graphs and Circulants

Using Mutation to Automatically Suggest Fixes for Faulty Programs

Automated Freedom from Interference Analysis for Automotive Software

ExMAn: A Generic and Customizable Framework for Experimental Mutation Analysis

On Code Coverage of Extended FSM Based Test Suites: An Initial Assessment

On the Hardness of Counting the Solutions of SPARQL Queries

System Testing of Timing Requirements based on Use Cases and Timed Automata

Verification Overview Testing Theory and Principles Testing in Practice. Verification. Miaoqing Huang University of Arkansas 1 / 80

EECS 144/244: Fundamental Algorithms for System Modeling, Analysis, and Optimization

Induction and Semantics in Dafny

Nondeterministic Query Algorithms

Timed Automata: Semantics, Algorithms and Tools

An Eclipse Plug-in for Model Checking

Designing and documenting the behavior of software

Distributed Objects with Sense of Direction

Transcription:

Efficient Mutation Killers in Action Bernhard K. Aichernig, Harald Brandl, Elisabeth Jöbstl Institute for Software Technology Graz University of Technology Graz, Austria {aichernig, brandl, joebstl}@ist.tugraz.at Willibald Krenn Maxeler Technologies, Ltd 1 Down Place London W6 9JH, UK. willibald.krenn@gmx.at Abstract This paper presents the techniques and results of a novel model-based test case generation approach that automatically derives test cases from UML state machines. Mutation testing is applied on the modeling level to generate test cases. We present the test case generation approach, discuss the tool chain, and present the properties of the generated test cases. The main contribution of this paper is an empirical study of a car alarm system where different strategies for killing mutants are compared. We present detailed figures on the effectiveness of the test case generation technique. Although UML serves as an input language, all techniques are grounded on solid foundations: we give UML state transition diagrams a formal semantics by mapping them to Back s action systems. Keywords-test case generation; mutation testing; ioco; action systems; Unified Modeling Language I. INTRODUCTION Today s dependable computer-based infrastructures rapidly grow in complexity due to a continuous evolution towards very large, heterogeneous, highly dynamic and ubiquitous computer systems. This trend of a growing complexity is a serious challenge to the task of engineering trustworthy systems: the more complex a system is, the more difficult is the verification of the fulfillment of its dependability requirements. It seems that despite the many advances in automated verification, i.e. in model checking and theorem proving, the demand for new features and flexibility always creates systems that establish the next limits for automated verification. However, the situation is not hopeless. Where formal verification is not feasible, a formal testing approach can be applied. In this work we present a formal model-based testing approach for generating test cases from UML state machines. Two features make our testing formal: (1) we give UML a formal semantics, and (2) we rely on a sound testing theory including a precise notion of conformance. In order to give UML a formal semantics, we have developed a mapping from UML state machines to labeled transition systems via an object-oriented action system formalism. By translating UML models to labeled transition systems (LTS) we gain access to the existing testing theories based on LTS: in order to support partial, non-deterministic models, we distinguish between controllable (input) and observable (output) labels, and use the conformance relation ioco [2] as a basis for test case generation. We follow a classical and a non-classical test selection strategy. The classical approach is implemented via a mapping from our LTS interpretation of action systems to the CADP 1 tools. This gives us access to the TGV test case generator [3] as well as to model checkers and simplifiers of CADP. The latter we use for checking both, the models as well as the translation chain from UML. The non-classical test generation technique emphasized in this paper is model-based mutation testing. It adds a faultcentered testing approach to the tool chain. Program mutation testing provides a method of assessing and improving a test suite by checking if its test cases can detect a number of injected faults in a program. The faults are introduced by syntactically changing the source code following patterns of typical programming errors [4], [5]. However, in our approach we apply model-based mutation testing. The idea is to mutate the UML models and generate those test cases that would kill a set of mutated models. The generated tests are then executed on the system under test (SUT) and will detect if a mutated UML state machine has been implemented. It is a complementary testing approach, well-suited for dependability analysis, since its coverage is measured in terms of faults. The mapping from UML and the general idea behind our test case generator have been described in detail elsewhere [1], [6], [7], [8]. In this paper, we focus on the characterization and evaluation of different test selection strategies. For illustration purposes, we have chosen a small demonstrator provided by our industrial partner Ford as a case study. Although the example is small, the tools are designed to cope with more complex control problems including interlocking of railway systems. The rest of the paper is structured as follows. Section II presents the model of our running example, discusses the mutations, and sketches our mapping from UML to LTS. The main contributions of this paper can be found in Sections III and IV. Section III introduces a formal characterization of our resulting test cases and an algorithm for the generation 1 http://www.inrialpes.fr/vasy/cadp/

«system_under_test» AlarmSystem Lock Unlock Close Open Figure 1. + alarmarmed [1] «environment» AlarmArmed SetOn() SetOff() + acousticalarm [1] «environment» AcousticAlarm SetOn() SetOff() + opticalalarm «environment» OpticalAlarm SetOn() SetOff() Testing interface of the car alarm system [1] «signal» Lock «signal» Unlock «signal» Close «signal» Open AlarmSystem_StateMachine Unlock OpenAndUnlocked Open Close Lock Unlock ClosedAndUnlocked OpenAndLocked Unlock Lock Close Open Alarm Activate Alarms /entry Deactivate Alarms /exit FlashAndSound 30 / Deactivate Sound ClosedAndLocked 20 Flash of adaptive test cases. Section IV presents different test selection strategies and the empirical results gained when applying them to our case study. Before concluding the paper in Section VI, we discuss related research in Section V. II. A UML MODEL In order to demonstrate the basic concepts of our test case generation approach, we use a simplified version of a car alarm system (CAS). The example is taken from Ford s automotive demonstrator within the MOGENTES 2 project. The following requirements were specified and served as the basis for our UML test model: R1 - Arming: The system is armed 20 seconds after the vehicle is locked and the bonnet, luggage compartment, and all doors are closed. R2 - Alarm: The alarm sounds for 30 seconds if an unauthorized person opens the door, the luggage compartment, or the bonnet. The hazard flasher lights will flash for five minutes. R3 - Deactivation: The anti-theft alarm system can be deactivated at any time, even when the alarm is sounding, by unlocking the vehicle from outside. A. Testing Interface As shown in Figure 1, the UML model resulting from the above stated requirements comprises four classes and four signals. The class AlarmSystem is labeled as system under test (SUT) and may receive any of the Lock, Unlock, Close, or Open signals. At the same time, the SUT calls methods of the classes AlarmArmed, AcousticAlarm, and OpticalAlarm all of them labeled as being part of the environment. In this way, the class diagram in Figure 1 specifies the observations we can make (all calls to methods being part of the environment) and the stimuli the SUT can take (all signals). Hence, the diagram specifies our testing interface. B. State Machine Figure 2 shows our CAS state machine diagram. From the state OpenAndUnlocked one can traverse to ClosedAnd- Locked by closing all doors and locking the car. Actions of closing, opening, locking, and unlocking are modeled by corresponding signals Close, Open, Lock, and Unlock. As specified in requirement R1, the alarm system is armed after 2 http://www.mogentes.eu/ Unlock Armed Show Armed /entry Show Unarmed /exit Figure 2. Close SilentAndOpen Open 300 State machine of the car alarm system 20 seconds in ClosedAndLocked. Upon entry of the Armed state, the model calls the method AlarmArmed.SetOn. Upon leaving the state, which can be done by either unlocking the car or opening a door, AlarmArmed.SetOff is called. Similarly, when entering the Alarm state, the optical and acoustic alarms are enabled. When leaving the alarm state, either via a timeout or via unlocking the car, both acoustic and optical alarm are turned off. When leaving the alarm state after a timeout (cf. requirement R2) we decided to treat the underspecification in the requirements in a way that the system returns to an armed state only in case it receives a close signal. Turning off the acoustic alarm after 30 seconds, as specified in requirement R2, is reflected in the time-triggered transition leading to the Flash sub-state of the Alarm state. C. Mutations Since we want to create test cases that cover particular fault models, we deliberately inject bugs into the specification and then create test cases that identify the differences. Therefore, we use various mutation operators. For example, one mutation operator sets guards of transitions to false 3. Others remove entry actions, signal triggers, or change signal events. For the CAS specification depicted in Figure 2, we obtain 76 mutated UML state machines. 19 mutants with a transition guard set to false, 6 mutants with a missing entry action, 12 mutants with missing signal triggers, 3 with missing time triggers, and 36 with changed signal events. We create first-order mutants, i.e., each mutated state machine covers only one particular mutation (one mutation operation in a particular place). Mutation testing relies on two assumptions: (1) competent engineers write almost correct code, i.e., faults are typically one-liners and (2) 3 This may lead to a transition transforming into a self-loop as the model will swallow the trigger event.

there exists a coupling effect so that complex errors will be found by test cases that can detect simple errors. Note that our approach also addresses the problem of equivalent mutants up to a certain search depth. We discover equivalent mutants during test case generation and skip them, since they show no deviating behavior we can test for. D. From UML to LTS via Action Systems Since our algorithms for test case generation work on the level of Labeled Transition Systems (LTS), the UML state machine model defined by the user has to be converted into an LTS. Basically, this conversion comprises the following steps: 1) The given UML model is transformed into a labeled and object-oriented intermediate representation that is based on Back s action system [9] formalism. During this step we set the exact UML semantics, e.g., the treatment of UML events and that of parallel regions. As a result, we derive an executable model of the system. 2) The object-oriented intermediate representation is simplified and a non-object-oriented (but still labeled) version of the action system is generated. 3) The action system derived in the second step is explored. This process yields the LTS of the UML model: Overly simplified, the execution of one labeled action within the action system adds one transition to the LTS. For further information about this conversion, we refer to our descriptions in [1]. We have developed tools that automate this process. Applying these tools to our model of the car alarm system (see Figure 2) yields the LTS shown in Figure 3. All labels in our system are prefixed by either obs (observable) or ctr (controllable). As explained in Section II-A, these prefixes are automatically deduced from the diagram specifying the testing interface (see Figure 1). An exception to this is the label obs after that stands for an observable timeout. Briefly speaking, after is observable because it represents a special case of the ioco timeout that is defined observable within the ioco theory (see Section III-A). III. TEST CASE GENERATION In this section, we explain our test case generation technique. First, we introduce the conformance relation that allows us to compare original and mutated specs. Then, we briefly explain our conformance checker. Next, we discuss the properties of the generated test cases and present an algorithm for test case selection. A. Input-Output Conformance Conformance relations are used to determine if a system under test (SUT) behaves correctly regarding a given specification. In our case, the SUT is represented by the mutated obs AcousticAlarm_SetOff 9 10 11 5 6 obs AlarmArmed_SetOff obs OpticalAlarm_SetOff Figure 3. ctr Open 8 obs AcousticAlarm_SetOn 7 obs OpticalAlarm_SetOn 15 obs AlarmArmed_SetOff 14 ctr Open 13 obs AlarmArmed_SetOn 12 obs after (c_waittime: 20 ) 16 0 ctr Open obs AcousticAlarm_SetOff 2 obs after (c_waittime: 30 ) obs after (c_waittime: 270 ) 17 4 obs AcousticAlarm_SetOff 1 obs OpticalAlarm_SetOff Labeled transition system of the car alarm system testing model while the specification is formed by the nonmutated testing model. In order to decide conformance, some testing hypotheses have to be stated [10]. One is that the implementation can be represented with the same formalism as the specification. In our application this is always the case since we decide the conformance between two specifications (an original and a mutated version). Since we are interested in input-output testing with partial system models we apply the ioco relation [2]. The trace semantics of an action system, see Section II-D and the work in [7], yields a Labeled Transition System (LTS) M. Thereby, a labeled transition system is defined as tuple S, L, T, s 0 where S is a countable set of states L = L U L I is a countable set of labels divided into input labels L I and output labels L U such that L I L U = T S (L {τ}) S is the transition relation, and s 0 S is the initial state. The special label τ denotes an internal action. We use the following notation for a given LTS, where s, s, s i S, S 3

S, a i L, σ L. s a s = df (s, a, s ) T s a = df s (s, a, s ) T s a = df s (s, a, s ) T s ɛ s = df s = s s 0... s n s = s 0 τ s1 τ... τ sn 1 τ sn = s s a s = df s 1, s 2 s ɛ s 1 a s2 ɛ s s σ s a = df s 0,..., s n s = s 1 a 0 2 a s1... n sn = s with σ = a 1... a n s σ = df s s σ s s after σ = df {s s σ s } The relation after 4 determines the set of states reachable after a trace σ starting from an initial state. Moreover, an LTS M has finite behavior if all traces have finite length. It is deterministic if σ L s 0 after σ 1 holds. For the ioco relation, SUTs are considered to be weak input-enabled, i.e., all inputs (possibly preceded by τ transitions) are enabled in all states: a L I, s S s. a This class of LTS is referred to as IOT S(L I, L U ) where IOT S(L I, L U ) LT S(L I L U ). A state s from which the system cannot proceed without additional inputs from the environment is called quiescent, denoted as (s). In such a state, all output and internal events are disabled: a L U {τ} s. a For observing quiescence, the transition relation T is extended by adding self-loops with the special label at quiescent states: T = df T {(s,, s) s S (s)}. Let M be the LTS over the alphabet L {τ, } resulting from adding self-loops to an LTS M. Then the deterministic version of M is called suspension automaton Γ. The set of suspension traces is: Straces(M ) = df {σ (L ) s 0 σ } The set of outputs that can occur in a state s S (in a set of states S S respectively) is defined as follows: out(s) = df {a L U s } a { (s)} out(s ) = df out(s) s S The ioco relation states that for all suspension traces in the specification, the outputs of the implementation after such a trace must be included in the set of outputs produced by the specification after the same trace. Formally, for an implementation model i IOT S(L I, L U ) and a specification s LT S(L I L U ) the relation ioco is defined as follows: i ioco s = df σ Straces(s) out(i after σ) out(s after σ) 4 Not to be confused with the timeout observation after (t) in Figure 3. Figure 4. The computation steps of Ulysses B. Conformance Checking specification AS and (2) a mutated version of the same We have implemented a tool for checking the inputoutput conformance of two system models named Ulysses. Figure 4 depicts the computation steps of our tool. Ulysses expects two labeled action systems as input: (1) a system specification AS M. Section II-D has already dealt with the transformation from a UML model to an LTS. The last step of this conversion is actually performed by the Ulysses tool by exploring a given labeled action system which yields its LTS semantics, see [7] for further details. Then the LTS is enriched by quiescence and subsequently converted into a deterministic automaton. By executing these steps, which are depicted in the first box of Figure 4, we have gained a so-called suspension automaton. Ulysses generates the suspension automata for both input models AS and AS M. Afterwards, the ioco check for these two models is performed (see the central box in Figure 4), which generates a product graph from which we extract controllable test cases (last box in the Ulysses process). Note that the calculation of the suspension automata and the synchronous product calculation modulo ioco (SP ioco ) are performed on-the-fly, which means that the automata are only unfolded as required by the conformance check, see [7]. Consider the example in Figure 5. The first two LTSs show the partial suspension automata of the specification and a mutant of the Car Alarm System. In the mutant, the controllable action Lock is a self-loop. The mutant is not ioco to the specification because the subset inclusion of the observations after the trace Lock, Close does not hold, i.e., out(mutant after Lock, Close ) = {} out(spec after Lock, Close ) = {after(20 )}. The product LTS (depicted on the right-hand side) may contain states with pass self-loops. They denote that the specified behavior is left after an unspecified controllable event or is aborted after a not implemented observable event. Furthermore, fail states, i.e., states with fail self-loops, denote that an unspecified observable event has occurred. In this case, we are able to derive a controllable test case that is able to detect this unspecified behavior (cf. LTS on the right-hand side). C. Test Case Selection and Coverage In the following we first show the required properties of our selected test cases and then present a selection algorithm for adaptive test cases.

Specification Mutant pass Product Test Case obs after ( 20 ) obs after ( 20 ) pass fail obs after ( 20 ) pass Figure 5. The two LTSs on the left show parts of the suspension automata of the CAS specification and a mutant. The two LTSs on the right depict the resulting ioco product and a selected test case. Given a product LTS (S P, L P, T P, s P 0) being the result of an ioco check and a set F ail S P denoting the set of fail states. We define an unsafe state as a state after which we may fail. Unsafe = df {s S P s a f f F ail a L U } Unsafe states play the central role in our test case generation strategy, since they are the test goal a test case should cover. Below, we present the general properties of a generated test case LTS T C = (S T C, L T C, T T C, s T 0 C ) that is selected from a product. S T C \{pass, inconc} S P L T C L P s T 0 C = s P 0 (inclusion) a s s {pass, inconc} (sink states) s = pass u Unsafe u a s s Fail a L U (s S T C s a s b ) = (a, b L I a = b) (passing) a, b L U (controllability)! u S T C (u Unsafe) u a pass (test goal unique) σ s T C 0 σ u u Unsafe (test goal reachable) A test case is a sub-transition system of the calculated product extended with two additional verdict states pass and inconc (controllability). In the test case, a sink state is a verdict state pass or inconc. Note, fail verdicts are implicit and not included (sink states). The pass verdict is characterized by successfully passing an unsafe state (passing). A test case does not contain choices over controllables, see also [2] (controllability). Reaching an unsafe state is the test goal of our mutation testing strategy. Hence, per test case exactly one unsafe state precedes a pass verdict state (test goal unique). Finally and most importantly, the test case must be able to reach its test goal, i.e., the unsafe state (test goal reachable). There are two kinds of test cases that may reach our test goal, i.e., a given unsafe state: First, a linear test case that includes one path to the unsafe state. Second, a branching adaptive test case that may include several paths to an unsafe state. In the following, we discuss the properties of the two kinds. Linear Test Cases: are necessary if the target test harness does not support branching behavior. The following two additional properties characterize linear test cases:! σ s T C 0 σ u u Unsafe s T C a inconc s T C σ u u Unsafe (linear test case) s ((s T C, a, s ) T P a L U a hd(σ)) (inconclusive linear) Such a test case contains exactly one path to the unsafe state (linear test case). Since a model s behavior may branch, an observation may lead away from the linear path. In this case, the test has to be stopped with an inconclusive verdict (inconclusive linear). Here, the head operator hd returns the first element in the trace σ. Adaptive Test Cases: integrate several paths to the unsafe state into one test case. They only give an inconclusive verdict if it is impossible to reach the unsafe state: s T C a inconc s T C σ u u Unsafe s ((s T C, a, s ) T P a L U s σ u) (inconclusive adaptive) Note the difference to the linear test case in the last conjunct. A linear test case reports inconclusive if an observation leads away from the single path to the unsafe state. In contrast, in the adaptive case, inconclusive is only reported, if after an observation we are unable to reach the unsafe state. T C u = df gettc (s 0, {u}) {(u, a, pass) s u a s a L U s / Fail} (adaptive test case) Algorithm 1 describes the selection of adaptive test cases, which is represented by the extraction and controllability box in Figure 4. The input of this algorithm is the product LTS and an unsafe state u. The product LTS is

Algorithm 1 gettc (s, Goal) : P(S L (S inconc)) 1: if s Goal then 2: return 3: else 4: σ := shortesttrace(s, Goal) 5: if σ = then 6: return {(s, a, inconc) s s a s a L U s / Fail} 7: else 8: E := edges(σ) 9: Goal := Goal states(e) 10: return E {{(s 1, a, s 2 ) T P } gettc (s 2, Goal) a, s 2 (s 1, a, s 2) E a, a L U a a s 2 / Fail} 11: end if 12: end if constructed on-the-fly as described in Section III-B either until a difference regarding ioco is found or a defined search depth is reached. In the following we denote set variables with capital letters. We obtain an adaptive test case T C u by calling gettc (s 0, {u}). A test case is a selection of transitions in the product LTS plus transitions to the test verdict states pass and inconc. Hence, a test case has the type P(S (L ) (S pass inconc)). By searching for the shortest trace from the initial state to an unsafe state and recursively extending this trace for all branching output transitions, the obtained test case complies with the controllability requirement (controllability). In Line 1 it is checked if the current state is already a goal state. If it is a goal state the empty set is returned. In Line 4 the shortest trace between a state s and one state in the set of goal states is determined. Note that there can exist several shortest traces of same length. In this case, we nondeterministically choose one. If there exists no such trace then all observations in state s terminate in an inconclusive state. Otherwise the transitions E along trace σ (Line 8) are part of the test case. The transitions of a trace are determined by the function: edges : (L ) P(S (L ) S). In Line 9, the set of states in E obtained by the function states are added to the set of goal states. Hence, the goal becomes to reach one state of the test case which in turn leads to an unsafe state. Next, the test case is recursively extended by all branching observable events along the trace σ (Line 10). Here, the set comprehension creates a set of sets of transitions. Each set corresponds to a subgraph in the test case after a branching observation. The recursive algorithm terminates when all branching outputs have been processed. Finally, the graph obtained from gettc is extended with the transitions to the pass state, see Definition (adaptive test case). IV. EXPERIMENTAL RESULTS In the preceding sections, we have discussed the theoretical basis of our test case generation approaches. This section goes one step further as we present the empirical results gained when applying eight different test case generation approaches to the car alarm system. We start our discussion with a summary of the different test case generation approaches before evaluating their fault detection capabilities. A. Test Case Generation Results We compare eight different test case generation approaches called A1 to A8. Generally speaking, A1 to A6 are fault-based approaches, A7 is based on random testing, and approach A8 uses test cases that were manually designed. All fault-based approaches use a set of 76 faulty specifications (cf. Section II-C) as input to test case generation. Note that because the car alarm system is deterministic, all test cases are linear. While the test cases in approach A1 and A2 have been generated via straightforward path search the approaches A3 A6 employ the test case algorithm 1. In A7 we generate test cases randomly and due to algorithm 1. Table I highlights the main differences between the approaches regarding generated test cases. Approach A1: Within the first approach, the product graph of the ioco check is first transformed into a tree structure with a maximum depth of 10 and a two-times maximum visit per state per trace. After tree unfolding the graph, we generate linear test cases for all paths that lead to an unsafe state in the tree. As can be seen in the table, this greedy test case generation strategy produces a very large number of tests. Also, approximately 75% of the generated tests are duplicates. From the non-duplicate test cases, we could exclude another 562 tests that are a complete subsequence of one of the other remaining test cases. Hence, about 3500 tests remain. Due to the vast amount of test cases generated by A1, we refrained from executing the tests on the CAS implementations. Approach A2: The second test case generation strategy directly works on the product graph and extracts only one arbitrary linear test per unsafe state. Notice that one mutant may still involve more than one unsafe state in the product graph. This time, we could identify 58% of duplicate test cases and another 22 were covered as a subsequence in other test cases. It has to be said that we allowed for tests with a maximum length of 14 in this approach, thus generation times are not directly comparable between A1 and A2. We verified that all unique test cases with a length of up to 10 that were produced by this approach were included in the set of tests generated by the first approach. Approach A3: The third approach is similar to the second one, except that the depth is theoretically unbounded since the test case generator applies algorithm 1. Therefore, the generation time is not comparable with approaches A1 and A2 (but with A4 to A7).

A1 A2 A3 A4 A5 A6 A7 A8 Max. Depth 10 14 23 23 23 150 (19) 150 30 Gen. TCs [#] 16 210 302 504 129 63 11 3 9 Duplicates [#] 12 179 174 217 0 0 0 0 0 Unique [#] 3 469 110 269 123 59 11 3 9 Gen. Time [min] 188 91 23 70 23 10 0.25 - Table I NUMBER OF GENERATED TEST CASES Approach A4: The fourth approach builds on A3 but avoids creating test cases for unsafe states in a given product graph which are already covered by existing test cases. In order to check if a certain unsafe state is covered by an existing test case we generate a test purposes tp for that unsafe state. Then the existing test cases are checked by computing the synchronous product with tp. This is similar to the synchronous product calculation in the tool TGV[3], however TGV computes it between test purpose and specification. A test case tc satisfies a test purpose if the product calculation prunes no events from tc, i.e. tc tp = tc. The generated test purpose ensures that a given test case passes through the unsafe state to a pass state. Given an unsafe state u we determine the set of states L2U which lead to u, i.e. L2U = df {s S σ s σ u}. The set of pass states associated with u are Pass = df {s S a L U (u, a, s) T s / Fail}. The resulting test purpose tp u has the transition relation T u = df {(s 1, a, s 2 ) T s 1, s 2 L2U (s 1 = u s 2 Pass)} {(s,, s) s Pass}. The remaining behavior after reaching a state s Pass is not of interest, denoted by the label allowing any transitions to occur thereafter. This approach yields one test case per unsafe state. Note however, that generated test cases still can be included in other test cases. This depends on the order of processed unsafe states. If we would start with deep unsafe states and proceed to shallow ones it is theoretically possible that no generated test case is included in another one. While the total number of generated test cases decreases to 129 (from 504), the time used to generate them increases to 70 minutes (from 23). This is because we compute the check for every unsafe state and in the worst case for all test cases generated so far. In effect, A4 checks whether an existing test case already covers an unsafe state in the ioco product before creating a new test case. If an unsafe state (there may be several per mutated specification) is not covered, a new test case is emitted. Approach A5: Approach A5 also avoids creating duplicate test cases. However, A5 further tries to minimize the size of the generated test suite. Before creating test cases for a mutated specification, A5 first checks whether any of the previously created test cases is able to kill the mutated specification. Therefor, the synchronous parallel execution of the test case tc with the mutated specification under test m is applied. The following rules define the operational semantics for killing a mutated specification. tc a tc m a m tc m a (1) a L a I tc tc m a m tc m tc m a (2) tc m a L U tc a tc m a m tc m a fail m (3) Rule (1) describes the case where tc and m synchronize on common events and proceed to their next state. Due to the input enabledness assumption the mutated specification has to accept all input events in every state. This is realized by making every state of m input complete by adding self loops for the remaining input events, see Rule (2). Rule (3) states that the test case reaches a fail state when the mutant produces an output event which the test case cannot follow. Given these rules a mutant is killed when a fail state can be reached, i.e. σ (L ) tc m σ fail m. The check is done without calculating the full ioco product between the specification and the mutant, which is the first difference to A4. A4 always calculates the full ioco product. If an existing test is able to kill the mutant, the test suite is considered strong enough and no new test cases are generated for the mutant. Notice that this is the second difference to A4 as A4 will only skip test case generation for covered unsafe states, while A5 does never generate any additional test case for a killed mutant. Due to this minimization, approach A5 is sensitive to the ordering of mutants. Notice that A5 starts with an empty test suite. Approach A6: Approach A6 is like A5 but instead of starting with an empty test suite, A6 uses one randomly generated test case to start with. In effect, A6 is a combination of random (A7) and fault based testing (A5). Within Table I, the maximum depth not put in brackets is the depth of the randomly generated initial test case while the figure in brackets is the maximum depth of the additionally generated tests to cover all faulty specifications. Approach A7: This approach uses a random selection strategy in order to generate test cases. Put differently, A7 is not a fault-based test case generation approach and included for evaluation purposes only.

Mutants Equiv. Pairwise Different Equiv. Faults SetState 6 0 1 5 Close 16 2 6 8 Open 16 2 6 8 Lock 12 2 4 6 Unlock 20 2 8 10 Constr. 2 0 1 1 Total 72 8 26 38 Table II INJECTED FAULTS INTO THE CAS IMPLEMENTATION. Approach A8: Finally, we compare our test case generation approach based on UML with manually created test cases. More precisely, we generated 9 different test purposes by hand and let TGV [3] create test cases. 3 out of the 9 test cases check for observable timeouts (time-triggered transitions: 20, 30, 300 sec. delay). 4 test cases check the entry and exit actions of the states Armed and Alarm. One test case checks for the deactivation of the acoustic alarm after the timeout and one more complex test case has a depth of 30 transitions going once through the state SilentAndOpen to Armed before going to Alarm again and leaving after the acoustic alarm deactivation by an unlock event. Hence, each observable event is covered by at least one test case. During the creation of the test purposes, we relied on a printout of the UML state machine. B. Test Case Execution Results We applied classical mutation analysis in order to evaluate the effectiveness of our different test suites. For this purpose, we have implemented the CAS in Java based on the state machine of Figure 2. In order to derive a set of faulty implementations, we used the µjava [11] tool: in total, µjava gave us 72 mutated implementations. After careful inspection, 8 of these mutated implementations were found to be equivalent to the original program, and another set of 26 mutants was found to be equivalent to other mutants - forming 26 equivalent pairs. Hence, a sum of 38 (72-8 - 26) different faulty implementations of the CAS remain. Further details are shown in Table II. For each method, the table lists the total number of mutated implementations, the number of mutants that turned out to be equivalent to the original implementation, and the number of equivalent pairs of mutated implementations. The methods Close, Open, Lock, and Unlock are public ones and handle the equally named external events while SetState and the constructor (Constr) are internal methods. From the table, one can observe that the mutation on internal methods has a strong effect on the external behavior since there are no equivalent mutants for these methods. In the following, we use the 38 unique faulty CAS implementations to evaluate the effectiveness of our generated test cases. Of course, all tests were validated on the non-mutated CAS implementation. A2 A3 A4 A5 A6 A7 A8 SetState 0 0 0 0 0 0 0 Close 1 0 0 0 0 0 2 Open 0 0 0 1 0 0 4 Lock 0 0 0 0 0 0 2 Unlock 1 0 0 0 0 1 5 Constr. 0 0 0 0 0 0 0 Total 2 0 0 1 0 1 13 Detection Rate [%] 95 100 100 97 100 97 66 Impl. Coverage [%] 99 99 99 99 99 99 88 Table III OVERVIEW OF HOW MANY FAULTY SUTS COULD NOT BE KILLED BY THE TEST CASES GENERATED WITH DIFFERENT APPROACHES. Table III gives an overview of the number of survived faulty implementations for each test case generation approach. As can be seen from the table, the approaches A3, A4, and A6 were able to reveal all faults. The table also proves that the minimization algorithm applied in approach A5 reduces the fault-detection capabilities. Despite random testing (A7) did not find all faulty implementations, it proved quite effective in our setting. It has to be noted, however, that we allowed for an appropriate depth of the random test cases. Summing up, A5 and A7 still have a fault detection rate of 97%. The reason for the bad performance of A2 is the fact that the two surviving faulty implementations need tests with a depth of more than 14 interactions to be revealed and A2 s tests are restricted to a depth 14. The last column shows the results of running the manually designed tests (A8). Overall, 25 mutants were killed which results in a detection rate of 66%. Clearly, the figures show that in order to have a meaningful test suite, more (diverse) test cases have to be generated. Partly, this lack of diverse test cases is based on the deterministic test selection behavior of TGV: all TGV based tests have almost the same test sequence from OpenAndUnlocked to ClosedAndLocked, although alternative paths are possible. Often, coverage metrics on the implementation s source code serve as a quality measure to describe the adequacy of a test suite. Therefore, we have measured the coverage on the implementation in terms of basic block coverage. The approaches A2 - A7 achieve a coverage of 99%, whereas A8 (TGV) only results in a basic block coverage of 88%. By comparing the last two rows of Table III, it becomes obvious that a high code coverage does not automatically guarantee high fault detection rates, which we aim for. In summing up, the results show that our approaches are powerful in covering the implementation s source code and more importantly in detecting faults. However, the depth of our conformance analysis is critical as too less depth results in missing test cases and, in this example, in undetected faults. The results also show that the 3500 test cases of the first approach were by far too many: for the given

A3 A4 A5 Gen. TCs [#] 469 58 32 Gen. Time [min] 10:05 21:52 14:49 Table IV NUMBER OF GENERATED TEST CASES (HAND-WRITTEN OOAS MODEL) model mutations, one path per mutation is sufficient to detect all faults, provided this path is long enough. Finally, the combined approach (A6) proved to be a nice trade-off between generation time and effectiveness. Beside using UML models we directly modeled the CAS in OOAS language. The transformation from UML to OOAS brings quite a big overhead: while the hand-written OOAS model contains 105 lines and 11 actions, the transformed UML model results in 750 lines of code and 55 actions. This is mainly because UML is intended to specify systems on the implementation level rather than on an abstract requirement level. For instance, the whole event signaling mechanism of UML has to be transformed to OOAS constructs. For a comparison with the UML-based approach we implemented a mutation tool which created 442 mutated OOAS specifications. Table IV shows the number of test cases with according generation times for approaches A3- A5. Each test suite of the three approaches was able to detect all faulty implementations. The results show that our selection strategies are able to efficiently minimize test suites for a large number of mutated specifications. V. RELATED RESEARCH There exist already various research papers on test generation from UML state charts. Gnesi et al. [12] define the semantics of a subset of UML state charts in the form of transition systems with transitions labeled by input/output pairs. For this kind of models, they give a formal conformance relation similar to ioco and present an algorithm to automatically derive test cases. Seifert et al. [13] define so-called Compact Semantic Automaton (CSA) in order to efficiently represent the semantics of a UML state chart. From CSAs, they derive traces of observable events which serve as input for the test case generation algorithm defined by Tretmans [2]. Fröhlich et al. [14] systematically transform use cases into UML state charts and generate test suites with a given coverage level by applying AI planning methods. Model-based mutation testing was first used for predicatecalculus specifications [15]. Later, Stocks applied mutation testing to formal Z specifications [16] without automation. Due to model checking techniques, full automation became feasible. By checking temporal formulae that state equivalence between original and mutated models, counterexamples are generated, which serve as test cases [17]. In contrast to this state-based equivalence test, we check for input-output conformance allowing non-deterministic models. The idea of using an ioco checker for mutation testing comes from Weiglhofer, who tested against Lotos specifications [18]. To our knowledge, we are the first who apply this technique to UML state machines. Indeed, there has been previous work on mutation testing of UML state machines but in terms of model validation [19]. It seems that we are the first who actually generate test cases from mutated UML state machines. The work in [20] deals with mutation-based test case generation for probabilistic finite state machines. The authors present mutation operators and describe how to create input sequences to kill a given mutated state machine. In [21] state-based testing of classes is investigated. The authors present results for testing state charts and evaluate their approaches on a set of mutated implementations. Regarding time, we do not fully support the interleaving semantics of parallel running timers like UPPAAL [22]. VI. CONCLUSION We have presented our UML-based test case generation approach in a complete and concise manner. Other novelties covered in this paper are the formalization of our test cases properties and the adaptive test case selection algorithm. The main contribution, however, is the characterization and comparison of six different fault-based test case selection strategies. All of the presented strategies have been implemented in our tool chain. When fed with an UML model as input, it generates a test suite of possibly adaptive, ioco-conforming test cases. We have shown the effectiveness of our approaches in comparison to random testing and manual test case generation. The experiments indicate that the most promising approach is a clever combination of random exploration and conformance checking (Approach A6). The former is fast but incomplete with respect to covering the model mutations. The latter is complete, but expensive. The car alarm system is small but non-trivial: it involves hierarchical states, entry-exit actions with methods defined in class diagrams. Currently, we are working on larger case studies and the refinement of our tools. Furthermore, we investigate approaches to minimize the needed mutations. ACKNOWLEDGEMENT Research herein was funded by the EU FP7 project ICT- 216679, Model-based Generation of Tests for Dependable Embedded Systems (MOGENTES). We want to thank our colleagues Rupert Schlick and Wolfgang Herzner from AIT (Austrian Institute of Technology) for the discussion on the paper. They also prepared the initial UML model, the UML mutation operators, and in collaboration with the authors defined the UML to OOAS mapping. Johannes Reiter (AIT) helped in developing the UML to OOAS conversion tool. The requirements for the CAS example were provided by Ford.

REFERENCES [1] W. Krenn, R. Schlick, and B. K. Aichernig, Mapping UML to labeled transition systems for test-case generation - a translation via object-oriented action systems, in FMCO, 2009, pp. 186 207. [2] J. Tretmans, Test generation with inputs, outputs and repetitive quiescence, Software - Concepts and Tools, vol. 17, no. 3, pp. 103 120, 1996. [3] C. Jard and T. Jéron, TGV: theory, principles and algorithms, STTT, vol. 7, no. 4, pp. 297 315, 2005. [4] R. G. Hamlet, Testing programs with the aid of a compiler, IEEE Transactions on Software Engineering, vol. 3, no. 4, pp. 279 290, July 1977. [5] R. DeMillo, R. Lipton, and F. Sayward, Hints on test data selection: Help for the practicing programmer, IEEE Computer, vol. 11, no. 4, pp. 34 41, April 1978. [6] B. K. Aichernig, H. Brandl, E. Jöbstl, and W. Krenn, Modelbased mutation testing of hybrid systems, in FMCO, 2009, pp. 228 249. [7] H. Brandl, M. Weiglhofer, and B. K. Aichernig, Automated conformance verification of hybrid systems, Quality Software, International Conference on, vol. 0, pp. 3 12, 2010. [8] B. K. Aichernig, H. Brandl, E. Jöbstl, and W. Krenn, UML in action: A two-layered interpretation for testing, in UML&FM, ser. ACM Software Engineering Notes (SEN), 2010, in press. [9] R.-J. Back and R. Kurki-Suonio, Decentralization of process nets with centralized control, Distributed Computing, vol. 3, no. 2, pp. 73 87, 1989. [10] G. Bernot, M.-C. Gaudel, and B. Marre, Software testing based on formal specifications: a theory and a tool. Software Engineering Journal, vol. 6, no. 6, pp. 387 405, 1991. [11] Y.-S. Ma, J. Offutt, and Y.-R. Kwon, Mujava: a mutation system for java, in ICSE 06: Proceedings of the 28th international conference on Software engineering. New York, NY, USA: ACM, 2006, pp. 827 830. [12] S. Gnesi, D. Latella, and M. Massink, Formal test-case generation for UML statecharts, in Proceedings of the 9th IEEE International Conference on Engineering of Complex Computer Systems. IEEE CS, 2004, pp. 75 84. [13] D. Seifert, S. Helke, and T. Santen, Test case generation for UML statecharts, in Ershov Memorial Conference, ser. Lecture Notes in Computer Science, vol. 2890. Springer, 2003, pp. 462 468. [14] P. Fröhlich and J. Link, Automated test case generation from dynamic models, in Proceedings of the 14th European Conference on Object-Oriented Programming (ECOOP 2000), ser. LNCS, vol. 1850. Springer, 2000, pp. 472 492. [15] T. A. Budd and A. S. Gopal, Program testing by specification mutation, Computer languages, vol. 10, no. 1, pp. 63 73, 1985. [16] P. A. Stocks, Applying formal methods to software testing. Ph.D. dissertation, Department of computer science, University of Queensland, 1993. [17] P. E. Ammann, P. E. Black, and W. Majurski, Using model checking to generate tests from specifications. in Proc. of the 2nd IEEE International Conference on Formal Engineering Methods (ICFEM). IEEE CS, 1998, pp. 46 54. [18] B. K. Aichernig, B. Peischl, M. Weiglhofer, and F. Wotawa, Protocol conformance testing a SIP registrar: An industrial application of formal methods, in Proceedings of the 5th IEEE International Conference on Software Engineering and Formal Methods. London, UK: IEEE, 2007, pp. 215 224. [19] S. C. P. F. Fabbri and J. C. M. et al, Mutation testing applied to validate specifications based on Statecharts, in Proceedings of the 10th International Symposium on Software Reliability Engineering (ISSRE 99), Boca Raton, Florida. IEEE CS, 1999, pp. 210 219. [20] R. M. Hierons and M. G. Merayo, Mutation testing from probabilistic finite state machines, in TAICPART-MUTATION 07: Proc. of the Testing: Academic and Industrial Conference Practice and Research Techniques - MUTATION. IEEE Computer Society, 2007, pp. 141 150. [21] L. C. Briand, M. D. Penta, and Y. Labiche, Assessing and improving state-based class testing: A series of experiments, IEEE Transactions on Software Engineering, vol. 30, no. 11, pp. 770 793, 2004. [22] A. Hessel, K. G. Larsen, M. Mikucionis, B. Nielsen, P. Pettersson, and A. Skou, Testing real-time systems using uppaal, in Formal Methods and Testing, 2008, pp. 77 117.