Software Unit Testing Case Study:

51
Software Unit Testing Case Study: Money Class Conversation Simulation COP 4331 OO Processes for Software Development Dr. David A. Workman School of EE and Computer Science October 2, 2006

Transcript of Software Unit Testing Case Study:

Page 1: Software Unit Testing Case Study:

Software Unit TestingCase Study: Money Class

Conversation Simulation

COP 4331

OO Processes for Software Development

Dr. David A. Workman

School of EE and Computer Science

October 2, 2006

Page 2: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 2

Hierarchical View of Design

main

A::One() A::Two() A::Three()

B::One()C::One()

B::Two()

D::One()

E::Two()

E::One() D::Three()

D::Two()

Use Case #1

Use Case #3Use Case #2

Page 3: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 3

Design & Testing Principles

A

D

B C

Principle 1: Design should be performed “top-down” for each functional thread defined by a Use Case; that is, the interface and detailed design of a module should follow the design of all modules that functionally depend on it.

Rationale: By performing interface and detailed design top-down, we ensure that all requirements flow from dependent modules toward the modules they depend on. This principle attempts to postpone detailed design decisions until all functional requirements for a module are known.

Principle 2: Coding and Unit Testing should be performed “bottom-up” for a functional thread; that is, the unit testing of a module should precede the unit testing of all modules that functionally depend on it.

Rationale: By performing unit testing bottom-up, we ensure that all subordinate moduleshave been verified before verifying the module that depends on them. This principle attempts to localize and limit the scope and propagation of changes resulting from unit testing.

Page 4: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 4

Design & Testing Schedules

Layer 1 Layer 2 Layer 3 Layer 4 Layer 5A1, A2, A3 B1, D2, C1 E1, B2, D3 D1 E2

Development Layers for Detailed Design and Coding

Layer 1' Layer 2' Layer 3' Layer 4' Layer 5'B1, E1,E2, D3

A1, D2, D1 A2, B2 C1 A3

Development Layers for Unit Testing

B1 A1A1 B1 E1 E1A2 D2 B2 B3 D2 A2A3 C1 D3 D1 E2 E2 D1 B2 C1 A3

Effort

Time

Development Schedule

Build #1 (Integration Test 1)Build #2 (Integration Test 2)Build #3 (System Test)

See Notes

Page 5: Software Unit Testing Case Study:

Design & Test Example: Discrete Event Simulator

©Dr. David A. Workman

School of EE and Computer Science

University of Central Florida

March 29, 2007

Page 6: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 6

Use Case Diagram: Simulator

Simulation System

ConstructWorld

SpecifyInput

SimulateWorld

OutputWorldObjects

ReportSimulation

Data

InitializeSimulation

Simulation User

SpecifyOutput

SimulationInputFile

SimulationLogFile

Page 7: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 7

Simulation Architecture

Page 8: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 8

Simulation Architecture: Design Template

The Passive layer contains all classes that model problem data and inanimate objects of the simulated world. Agents make direct calls on passive objects, but must account for the simulation time consumed when doing so. Passive objects make direct calls to each other, if necessary. Passive objects may be passed from one Agent to another as part of a instance of some Message subclass.

This layer contains all the derived subclasses of Message. These classes are used to pass data for servicing interaction events between Agents. Only recipient Agent classes know the content and use of instances of these classes. Methods of Agents receiving messages optionally take parameters which are instances of one (or more) of the Passive classes and return an instance of class Message or one of its sub-classes. Instances of the root class Message carry no data and denotesignals that require some action on the part of the receiver Agent.

Virtual World

Message

Players

Agent

Event

2

Passive Class Layer

Message Layer

Agent Layer(Active Objects)

Interface and Control Layer

EventMgr *

1Other

Subclasses

All ActiveObjects

* *

All PassiveClasses/Objects

* *

*

This layer consists of all active object classes. Active objects must beinstances of some subclass of abstract class Agent. The simulation progresses as a result of Events created andserviced by Agents. An Event has four components: a Sender agent, a Recvr agent, an instance of some Messagesubclass, and an event time. When one Agent wishes to interact with another, it must do so by creating an Eventthat defines a “future” time at which the interaction will occur. The message component defines an action to theRecevr agent and possibly data necessary to complete the action.

SimModels Classes SimMgmt Classes

Page 9: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 9

Simulation Architecture: Student Conversation

Conversation

Message

Players

Agent

Event

2

Passive Class Layer

Message Layer

Agent Layer(Active Objects)

Interface and Control Layer

EventMgr *

1

AnswerMsg

* *

Question

SimModels Classes SimMgmt Classes

Student

Answer

QuestionMsg

Page 10: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 10

Design Graph: 1

0: Main()

4 Reusable Methods9 New MethodsClass Conversation

1: Conversation()

Class Agent2: Agent()3: operator>>()4: Get()

Class Student5: Student()6: Extract()7: Get()

1

5

6

3

2

7

4

Use Case 1

Page 11: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 11

Design Graph: 2

0: Main()

5 Reusable Methods9 New Methods

Class Conversation1: Conversation()8: Initialize()

Class Agent2: Agent()3: operator>>()4: Get()11: NameOf()21: ~Agent()

Class Student5: Student()6: Extract()7: Get()13: Initialize()16: AcceptQuest()

8

20

Class Players9: Players()12: setAgent()14: getAgent()15: getOther()20: ~Players()

Class Message10: Message()

9

2

12 13

11 14 15 16

Class SpeakMsg17: SpeakMsg()

17

10

Class Event18: Event()

18

Class EventMgr-3: EventMgr()19: postEvent()

19 21

Use Case 2

Page 12: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 12

Design Graph: 3

0: Main()

Class Conversation1: Conversation()8: Initialize()22: Insert()

Class Agent2: Agent()3: operator>>()4: Get()11: NameOf()21: ~Agent()23: oper<<()26: Put()

Class Student5: Student()6: Extract()7: Get()13: Initialize()16: AcceptQuest()24: Insert()25: Put

Class Players9: Players()12: setAgent()14: getAgent()15: getOther()20: ~Players()

Class Message10: Message()

Class SpeakMsg17: SpeakMsg()

Class Event18: Event()

Class EventMgr-3: EventMgr()19: postEvent()

25

24

22

23

26

Use Case 3 2 Reusable Methods3 New Methods

Page 13: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 13

Design Graph: 4

0: Main()

2

Class Conversation1: Conversation()8: Initialize()22: Insert()44: Simulate()

Class Agent2: Agent()3: operator>>()4: Get()11: NameOf()21: ~Agent()23: oper<<()26: Put()

Class Student5: Student()6: Extract()7: Get()13: Initialize()16: AcceptQuest()24: Insert()25: Put()37: Dispatch()39: doQuestion()40: AcceptAnswr()41: doAnswer()

Class Players9: Players()12: setAgent()14: getAgent()15: getOther()20: ~Players()

Class Message10: Message()30: Oper<<()31: Insert()32: Put()42: ~Message()

Class SpeakMsg17: SpeakMsg()33: Insert()34: Put()38: getHandlr()

Class Event18: Event()29: oper<<()35: getRecvr()36: getMsg()43: ~Event()

Class EventMgr-3: EventMgr()19: postEvent()27: moreEvents()28: getNextEvent()

17

27 28 29

23

24

25

26

30

32

3133

34

3635

40

3938

37

41

10

18 19

42

44

10 Reusable Methods8 New Methods

43

Use Case 4

Page 14: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 14

Design Graph: 2

0: Main()

Class Conversation1: Conversation()8: Initialize()22: Insert()44: Simulate()45: WrapUp()46: ~Conversation()

Class Agent2: Agent()3: operator>>()4: Get()11: NameOf()21: ~Agent()23: oper<<()26: Put()

Class Student5: Student()6: Extract()7: Get()13: Initialize()16: AcceptQuest()24: Insert()25: Put()37: Dispatch()39: doQuestion()40: AcceptAnswr()41: doAnswer()47: ~Student()

Class Players9: Players()12: setAgent()14: getAgent()15: getOther()20: ~Players()

Class Message10: Message()30: Oper<<()31: Insert()32: Put()42: ~Message()

Class SpeakMsg17: SpeakMsg()33: Insert()34: Put()38: getHandlr()

Class EventMgr-3: EventMgr()19: postEvent()27: moreEvents()28: getNextEvent()48: ~EventMgr()

4645

47

Use Case 5Class Event18: Event()29: oper<<()35: getRecvr()36: getMsg()43: ~Event()

1 Reusable Methods3 New Methods

21 Reusable27 New----------------48

Total Methods

4 Reusable4 New---------------8

Total Classes

Page 15: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 15

Scheduling

Development ScheduleUse Case 1

Use Case 3

Use Case 5

Use Case 4

Use Case 20: Main()

1

5

6 3

2

74

8

20

92 12

13

1114

15

161710

18

19

21 25 24 222326

17

27

28

29

23242526

30

32

31

3334

36

3540

39

38

3741

10

18

19

42

44

43

46

45

47

Page 16: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 16

Money ClassMoney

Char signInt dollarsInt cents

Money(); Money(ifstream&); Money(char,int,int); getSign():char getDollars():int; getCents():int;operator-() :Money; operator-(Money):Money;operator+(Money):Money; operator==(Money):bool; operator<(Money):bool;operator>(Money):bool; operator<=(Money):bool; operator>=(Money):bool; Extract(ifstream&)=>TokenError Insert(ostream&);operator>>(ifstream&,Money&) operator<<(ostream&,Money&)#Get(ifstream&) #Put(ostream&);-toInt(Money):int-toMoney(int):Money

Money(fin)

Extract(fin)

Get(fin)

Money()

Money(char,int,int)getSign()

getDollars()

getCents()

booleanoperators()

*

binaryoperators()

toInt(Money) toMoney(int)

*

Insert(fout)

Put(fout)

operator>>(fin)

operator<<(fout)

TokenError

1

1

1

1

1

1 1

2

2

22

2

33

3

34

4

4 4

Initially make public

Page 17: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 17

Money Class Test Driver 1#include "IOMgmt.h"using namespace IOMgmt;#include "Money.h"int main(){ InMgr finMgr("Enter Input File (Test1):"); ifstream& fin = finMgr.getStream(); OutMgr foutMgr("Enter Output File(Test1):"); ostream& fout = foutMgr.getStream(); int num_cases; char sign; int dollars, cents; fin >> num_cases; for(int I = 1; I <= num_cases; I++) { fin >> sign >> dollars >> cents; fout << "Case #" << num_cases – I + 1 << endl; fout << "Input Data: " << sign << dollars << cents << endl; Money M1(sign,dollars,cents); int M1cents = toInt(M1); Money M2 = toMoney(M1cents); char Sign = M2.getSign(); int Dollars = M2.getDollars(); int Cents = M2.getCents(); fout << "M1cents: " << M1cents << endl; fout << "Sign = " << Sign << ", Dollars= " << Dollars << ", Cents= " << Cents << endl; }//for}//main-1

Page 18: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 18

Money Class Test Driver 2

#include "IOMgmt.h"using namespace IOMgmt;#include "Money.h"int main(){ InMgr finMgr("Enter Input File(Test2):"); ifstream& fin = finMgr.getStream(); OutMgr foutMgr("Enter Output File(Test2):"); ostream& fout = foutMgr.getStream(); int num_cases; char sign1, sign2; int dollars1, cents1, dollars2, cents2; fin >> num_cases; for(int I = 1; I <= num_cases; I++) { fin >> sign1 >> dollars1 >> cents1 >> sign2 >> dollars2 >> cents2; Money M1(sign1,dollars1,cents1), M2(sign2,dollars2,cents2); fout << "Case #" << I << endl; fout << "Input Data (M1): " << sign1 << dollars1 << cents1 << endl; fout << "Input Data (M2): " << sign2 << dollars2 << cents2 << endl; bool Reql, Rneq, Rless, Rgtr, Rleq, Rgeq; Reql = M1 == M2; Rneq = M1 != M2; Rless = M1 < M2; Rgtr = M1 > M2; Rleq = M1 <= M2; Rgeq = M1 >= M2; fout << "(==) " << Reql << " (!=) " << Rneq << //etc. Money Sum, Diff, Neg; Sum = M1 + M2; Diff = M1 – M2; Neg = -M1; fout << "Sum = " << Sum << ", Diff = " << Diff << ", Neg(M1) = " << Neg << endl; fout << "M1 = " << M1 << ", M2 = " << M2 << endl; }//for}//main-2

Page 19: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 19

Money Class Test Driver 3#include "IOMgmt.h"using namespace IOMgmt;#include "Money.h"int main(){ InMgr finMgr("Enter Input File(Test3):"); ifstream& fin = finMgr.getStream(); OutMgr foutMgr("Enter Output File(Test3):"); ostream& fout = foutMgr.getStream(); int num_cases; fin >> num_cases; for(int I = 1; I <= num_cases; I++) { Money M; try{ fout << "Case# " << I; fin >> M; fout << ": Money = " << M << endl; }//try catch(TokenError &e){ fout << ": " << e.getMsg() << endl; }//catch }//for}//main-3

Page 20: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 20

Testing Agent BehaviorsOnce the constructors, Insert, Put, Extract and Get methods have been written and tested, the way is clear to testsimulation initialization and execution behaviors. There are a couple of techniques that can be used to test specificEvents and consequently specific Agent behaviors.

class Conversation { //Virtual World public: Conversation(); ~Conversation(); void Initialize(); void Simulate(); void WrapUp(); void Put(); private int debugOption; //new simulation input paramter int numStudents; int numEvents; int lastEvent; AGENTPTR *students; //dynamic array of Agent* MSGPTR players; //pointer to Players message. void ExtractEvent(); //private method(s) for testing };//Conversation

Page 21: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 21

Testing Agent Behaviors

Void Conversation::Conversation(){ //parses image of virtual world object, Conversation. //if debugOpt = ON, then it calls ExtractEvent()}

void Conversation::ExtractEvent(){ //private method of Conversation //Has visibility to any data the Conversation constructor can see. //Parses the desired image of Event(s) for debugging purposes // Posts the constructed Event(s) to theEventMgr.}

SimModels.cpp

Page 22: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 22

Testing Agent Behaviorsclass Message {//concrete base class public: Message(int Handler,string Description); virtual ~Message() { } //destructor int getHandler() const { return handler;} //inspector friend ostream& operator<<(ostream &fout, Message &anyMsg) throw(IOError); friend ifstream& operator>>(ifstream& &fin, Message &anyMsg) throw(IOError, TokenError); //new protected: virtual void Insert(); virtual void Put (); virtual void Extract() throw(TokenError); //new virtual void Get() throw(TokenError); //new private: int handler; string description; };//Message

class SpeakMsg : public Message { // Inherits from Message public: SpeakMsg(int Handler, string Description, string Speak); ~SpeakMsg() { } string getContent() const { return content; } protected: virtual void Insert(); virtual void Put(); virtual void Extract() throw(TokenError); //reads default program input stream virtual void Get() throw(TokenError); //reads default program input stream private: string content; }; //SpeakMsg

Page 23: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 23

Testing Agent BehaviorsConversation{ debugopt: OFF

#students: 2Student{ name: Betty

questdelay: 5 ansrdelay: 2}StudentStudent{ name: Bart

questdelay: 3 ansrdelay: 4}Student

}Conversation

Conversation{ debugopt: ON

#students: 2Student{ name: Betty

questdelay: 5 ansrdelay: 2}StudentStudent{ name: Bart

questdelay: 3 ansrdelay: 4}Student

debug{ #events: 1 Event{ time: ttt sendr: Bart recvr: Betty msg: SpeakMsg{ handler: 3 description: Testing content: How_Are_You? }SpeakMsg

}Event }debug}Conversation

Page 24: Software Unit Testing Case Study:

Applications of theTheory Automata

and Regular Expressions

to Programmingand Software Testing

Presentation by

© Dr. David A. Workman

School of EE & CS

University of Central Florida

March 3, 2003

Page 25: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 25

Outline

1. A Little History of Programming

2. A Little Review of Theory (COT 4210)

3. An Example Applying Theory to Practice

4. Summary and Conclusion

Page 26: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 26

A Little History of Programming

• “Flow Diagram, turing machines and languages with only two formation rules.” by Bohm and Jacopini, CACM Vol. 9, No. 5 (May 1966)

Proved that all algorithms could be expressed using sequential execution assignment statements, conditional logic using if-then-else statements, and iteration using while statements.

• “Goto Statements considered harmful,” by Edsgar Dijkstra, CACM, Vol. 11, No. 3, March 1968, pp. 147-148.

– Contributions to the specification of ALGOL, 1957 – 60.– Cooperating Sequential Processes, 1966

– The THE Operating System, 1968

• ACM/A.M. Turing Award Citation, February 5, 1999: “Edsger Dijkstra was a principal contributor in the late 1950's to the development of the

ALGOL, a high level programming language which has become a model of clarity and mathematical rigor. He is one of the principal exponents of the science and art of programming languages in general, and has greatly contributed to our understanding of their structure, representation, and implementation. His fifteen years of publications extend from theoretical articles on graph theory to basic manuals, expository texts, and philosophical contemplations in the field of programming languages. “

Page 27: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 27

A Little Review of Theory

Definition 1. A Deterministic Finite Automata (DFA) is a 5-tuple, M = (Q, Σ , δ , q0, A), where Q is a finite set of states, Σ denotes the input alphabet, q0 denotes the unique start state, A a finite, possibly empty set of Accept states, and the behavior of M is specified by its transition (computation) function δ : Q × Σ→ Q.

We typically specify the behavior of a DFA, its d function, in the form of a State Transition Diagram such as the one shown below as an example.

154

3

2

starta

b

a

a

a

a

b

b

bb

Page 28: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 28

A Little Review of Theory

Definition 2. The Language Accepted by a DFA, is denoted L(M), and is given by

L(M) = { x ∈Σ* | δ ∗(q0, x) ∈ A }

where the function , δ∗ : Q × Σ * → Q, is an extension of the transition function to strings over the input alphabet.

What is L(M) for the DFA, M, given below???L(M) = { a, ab, abaaaaba, aaaaaaba, …. }

154

3

2

starta

b

a

a

a

a

b

b

bb

Page 29: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 29

A Little More Theory

Definition 3. The Language of Regular Expression, E(Σ), over alphabet Σ , is the set of strings over alphabet Σ’ = Σ ∪ { λ , φ , + , ∗ , ⋅ , ( , ) } given by the inductive definition: Basis: Σ ∪ { λ , φ } ⊂ E(Σ) .Inductive Rules: assume e, f ∈ E(Σ), then each of the following is a member of E(Σ), [1] (e)*[2] (e ⋅ f)[3] (e + f)

Definition 4. The Language defined by Regular Expression, e, is denoted L[e] and is defined recursively below.Basis: L[φ] = Φ (the empty set), and for e ∈ Σ ∪ { λ }, L[e] = {e}.Inductive Rules: e, f, g ∈ E(Σ), [1] if e = (f)*, then L[e] = L[f]* (Kleene-star operation)[2] if e = (f ⋅ g), then L[e] = L[f]L[g] (Language concatenation)[3] if e = (f + g), then L[e] = L[f] ∪L[g] (Language union)

Example. E( {a,b} ) = {φ , λ , a, b, (φ)*, (λ)*, (a)*, (b)*, (φ ⋅ λ), (a ⋅a), (b ⋅ φ), (φ + λ), (a +a), (b +φ), … (((a(ba))+(φ)*)+(φ((φ+λ))*))… }

Example. L[ (((a(ba))+(φ)*)+(φ((φ+λ))*))] = {aba, λ}

Page 30: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 30

A Little Review of Theory

• What is the significance (relevance) of DFAs (and their theory) ?• What is the significance of Regular Expressions (RE)?• How do these mathematical abstractions apply to programming?

SOME ANSWERS– DFAs are algorithmic abstractions– DFAs and REs can be used to model the lexical analysis function of real

compilers– DFA’s recognize Regular languages– RE’s also define Regular Languages

??? “Ho Hum, Yawn”

This could beYou!!!

Page 31: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 31

Example Method (C++)

void Server::Work(){

ifstream input; // input file streamofstream output; // output file streamTray tray;cout << "McDonald's Implementation in C++" << endl;cout << "by XXXXXXXXXX and YYYYYYYYYYY" << endl;cout << endl;

while(1) {

string szInputFileName; cout << "Please enter the name of the input file: "; cin >> szInputFileName; input.open(szInputFileName.c_str()); if( !input ) alpha: { cerr << endl << "No file named " << szInputFileName << " found." << endl; } else break;}

} //Server::WorkInsert Segment A(from next slide

1

2

3

5

4

6

16

A Basic Block of code is a sequence of declaration,assignment, and method call statements, that mayoptionally end with a gotoor contional goto statement.

Page 32: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 32

Example Method (C++)

FoodItems *pFood;

while(!input.eof()) { char szMarker[4]; input >> szMarker; strupper(szMarker); if(strcmp(szMarker, "$D") == 0) pFood = new Drinks; // drink else if(strcmp(szMarker, "$S") == 0) pFood = new Sandwiches; // sandwich else if(strcmp(szMarker, "") == 0) continue; // blank line; skip else throw InputException("Unknown type found " + string(szMarker)); pFood->Get(input); tray.Add_Item(pFood);} //while

Segment A

6

7

8

9 10

11 12

13

14

15

Page 33: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 33

Example Method (C++)

1

2

86

53

10 15

12

17

Exceptionexit

Normalexit

Systemexit

9

11

1416

7

4

13

F

T

F

F

FF

T

TT

T

Notes: This is an example ofa program flow graph, the subject of Bohm and Jacopini’s theorem.

Even though this algorithm waswritten using a “structured style”, the flow graph is not completely structured in the purest sense since there are multiple method exits due to exceptions.

Page 34: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 34

Example Method (C++)

1

2

86

53

10 15

12

Exceptionexit

Normalexit

9

11

14

16

7

4

13

F

T

F

F

F

F

T

TT

T

Note: We have modified the structured version to violate the principles of structured design ( 13 => 5 ).

To Re-Structure we apply the theory of DFAs and REs as follows:

(1) All conditional nodes become “states” in a DFA.(2) Transitions between states are labeled with the sequential computation thatconnects any pair of conditional nodes.(3) Unique transition sequences become “letters” in the DFA alphabet.

Page 35: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 35

Example Method (C++)

a = 123b = (4T)523c = (4F)6d = (7T)8e = (9T)(10)(15)f = (9F)g = (11T)(12)(15)h = (11F)i = (13T523)j = (13F)k = (7F)

start

Exceptionexit

Normalexit

9 11 14

16

74 13

a

b

c

k

d

e

f

g

h j

i

E4 = a + E4b + E13iE7 = E4c + E9e + E11gE9 = E7dE11 = E9fE13 = E11hE14 = E13jE16 = E7k

Define the following “alphabet”

Set up a system of Regular Equations

Solution for Paths = E16 + E14

E16 = ab*c[d ( e + f (g + hib*c)) ]*kE14 = ab*c[d ( e + f (g + hib*c)) ]*dfhjPaths = ab*c[d ( e + f (g + hib*c)) ]* (k+dfhj)

Page 36: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 36

Expression => Code

{ boolean X; 1;3; //a (2 = true) while( 4 ) { 5; 3 } //b* 6; //c X := true; // Boolean variable for exception handling while ( X and 7 ) { //7T 8; //d if( 9 ) { //9T 10; 15 //e } else { //9F = f if( 11 ) { //11T 12;15 //g else{ //h if( 13 ) { //13T 5; 3 //i while( 4 ) { 5; 3} //b* 6; //c = (4F)6 } else X = false; //13F = exception condition }//11 - else }//9 - else }// while(7 and X) if( not X ) throw(exception); //j = abnormal end } //k = normal end

Equivalent Structured Code

a = 123b = (4T)523c = (4F)6d = (7T)8e = (9T)(10)(15)f = (9F)g = (11T)(12)(15)h = (11F)i = (13T523)j = (13F)k = (7F)

Solution for Paths = E16 + E14

E16 = ab*c[d ( e + f (g + hib*c)) ]*kE14 = ab*c[d ( e + f (g + hib*c)) ]*dfhjPaths = ab*c[d ( e + f (g + hib*c)) ]* (k+dfhj)

Page 37: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 37

Summary & Conclusion

• Summary (What are the main points?)– DFAs and REs are more than just (equivalent) mathematical specifications for

Regular Languages and algorithms for lexical analysis, they are useful for modeling algorithms of any kind and complexity.

– Using algorithms for equivalence between DFAs and REs we were able to see why Bohm and Jacopini’s theorem is true, and why Dijkstra so strongly endorced the principles of structured programming.

• Conclusion (What have we learned?) The “marriage” between Theory and Practice is not “on the rocks”, this couple is

not “legally separated” or “divorced” with “irreconcilable differences,” they are a harmonious couple, inextricably entwined, cooperating and complementing each other. What mathematics has brought together, let no computer scientist put asunder!

Page 38: Software Unit Testing Case Study:

Applications of theTheory Automata

and Regular Expressions

to Programming

COT 4810: Topics in Computer Science

Spring 2003

Presentation by

© Dr. David A. Workman

School of EE & CS

University of Central Florida

March 3, 2003

Page 39: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 39

Outline

1. A Little History of Programming

2. A Little Review of Theory (COT 4210)

3. An Example Applying Theory to Practice

4. Summary and Conclusion

Page 40: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 40

A Little History of Programming

• “Flow Diagram, turing machines and languages with only two formation rules.” by Bohm and Jacopini, CACM Vol. 9, No. 5 (May 1966)

Proved that all algorithms could be expressed using sequential execution assignment statements, conditional logic using if-then-else statements, and iteration using while statements.

• “Goto Statements considered harmful,” by Edsgar Dijkstra, CACM, Vol. 11, No. 3, March 1968, pp. 147-148.

– Contributions to the specification of ALGOL, 1957 – 60.– Cooperating Sequential Processes, 1966

– The THE Operating System, 1968

• ACM/A.M. Turing Award Citation, February 5, 1999: “Edsger Dijkstra was a principal contributor in the late 1950's to the development of the

ALGOL, a high level programming language which has become a model of clarity and mathematical rigor. He is one of the principal exponents of the science and art of programming languages in general, and has greatly contributed to our understanding of their structure, representation, and implementation. His fifteen years of publications extend from theoretical articles on graph theory to basic manuals, expository texts, and philosophical contemplations in the field of programming languages. “

Page 41: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 41

A Little Review of Theory

Definition 1. A Deterministic Finite Automata (DFA) is a 5-tuple, M = (Q, Σ , δ , q0, A), where Q is a finite set of states, Σ denotes the input alphabet, q0 denotes the unique start state, A a finite, possibly empty set of Accept states, and the behavior of M is specified by its transition (computation) function δ : Q × Σ→ Q.

We typically specify the behavior of a DFA, its d function, in the form of a State Transition Diagram such as the one shown below as an example.

154

3

2

starta

b

a

a

a

a

b

b

bb

Page 42: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 42

A Little Review of Theory

Definition 2. The Language Accepted by a DFA, is denoted L(M), and is given by

L(M) = { x ∈Σ* | δ ∗(q0, x) ∈ A }

where the function , δ∗ : Q × Σ * → Q, is an extension of the transition function to strings over the input alphabet.

What is L(M) for the DFA, M, given below???L(M) = { a, ab, abaaaaba, aaaaaaba, …. }

154

3

2

starta

b

a

a

a

a

b

b

bb

Page 43: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 43

A Little More Theory

Definition 3. The Language of Regular Expression, E(Σ), over alphabet Σ , is the set of strings over alphabet Σ’ = Σ ∪ { λ , φ , + , ∗ , ⋅ , ( , ) } given by the inductive definition: Basis: Σ ∪ { λ , φ } ⊂ E(Σ) .Inductive Rules: assume e, f ∈ E(Σ), then each of the following is a member of E(Σ), [1] (e)*[2] (e ⋅ f)[3] (e + f)

Definition 4. The Language defined by Regular Expression, e, is denoted L[e] and is defined recursively below.Basis: L[φ] = Φ (the empty set), and for e ∈ Σ ∪ { λ }, L[e] = {e}.Inductive Rules: e, f, g ∈ E(Σ), [1] if e = (f)*, then L[e] = L[f]* (Kleene-star operation)[2] if e = (f ⋅ g), then L[e] = L[f]L[g] (Language concatenation)[3] if e = (f + g), then L[e] = L[f] ∪L[g] (Language union)

Example. E( {a,b} ) = {φ , λ , a, b, (φ)*, (λ)*, (a)*, (b)*, (φ ⋅ λ), (a ⋅a), (b ⋅ φ), (φ + λ), (a +a), (b +φ), … (((a(ba))+(φ)*)+(φ((φ+λ))*))… }

Example. L[ (((a(ba))+(φ)*)+(φ((φ+λ))*))] = {aba, λ}

Page 44: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 44

A Little Review of Theory

• What is the significance (relevance) of DFAs (and their theory) ?• What is the significance of Regular Expressions (RE)?• How do these mathematical abstractions apply to programming?

SOME ANSWERS– DFAs are algorithmic abstractions– DFAs and REs can be used to model the lexical analysis function of real

compilers– DFA’s recognize Regular languages– RE’s also define Regular Languages

??? “Ho Hum, Yawn”

This could beYou!!!

Page 45: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 45

Example Method (C++)

void Server::Work(){

ifstream input; // input file streamofstream output; // output file streamTray tray;cout << "McDonald's Implementation in C++" << endl;cout << "by XXXXXXXXXX and YYYYYYYYYYY" << endl;cout << endl;

while(1) {

string szInputFileName; cout << "Please enter the name of the input file: "; cin >> szInputFileName; input.open(szInputFileName.c_str()); if( !input ) alpha: { cerr << endl << "No file named " << szInputFileName << " found." << endl; } else break;}

} //Server::WorkInsert Segment A(from next slide

1

2

3

5

4

6

16

A Basic Block of code is a sequence of declaration,assignment, and method call statements, that mayoptionally end with a gotoor contional goto statement.

Page 46: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 46

Example Method (C++)

FoodItems *pFood;

while(!input.eof()) { char szMarker[4]; input >> szMarker; strupper(szMarker); if(strcmp(szMarker, "$D") == 0) pFood = new Drinks; // drink else if(strcmp(szMarker, "$S") == 0) pFood = new Sandwiches; // sandwich else if(strcmp(szMarker, "") == 0) continue; // blank line; skip else throw InputException("Unknown type found " + string(szMarker)); pFood->Get(input); tray.Add_Item(pFood);} //while

Segment A

6

7

8

9 10

11 12

13

14

15

Page 47: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 47

Example Method (C++)

1

2

86

53

10 15

12

17

Exceptionexit

Normalexit

Systemexit

9

11

1416

7

4

13

F

T

F

F

FF

T

TT

T

Notes: This is an example ofa program flow graph, the subject of Bohm and Jacopini’s theorem.

Even though this algorithm waswritten using a “structured style”, the flow graph is not completely structured in the purest sense since there are multiple method exits due to exceptions.

Page 48: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 48

Example Method (C++)

1

2

86

53

10 15

12

Exceptionexit

Normalexit

9

11

14

16

7

4

13

F

T

F

F

F

F

T

TT

T

Notes: We have modified the structure version to make it violate the principles of structured design ( 13 => 5 ).

To Re-Structure we apply the theory of DFAs and REs as follows:

(1) All conditional nodes become “states” in a DFA.(2) Transitions between states are labeled with the sequential computation thatconnects any pair of conditional nodes.(3) Unique transition sequences become “letters” in the DFA alphabet.

Page 49: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 49

Example Method (C++)

a = 123b = (4T)523c = (4F)6d = (7T)8e = (9T)(10)(15)f = (9F)g = (11T)(12)(15)h = (11F)i = (13T523)j = (13F)k = (7F)

start

Exceptionexit

Normalexit

9 11 14

16

74 13

a

b

c

k

d

e

f

g

h j

i

E4 = a + E4b + E13iE7 = E4c + E9e + E11gE9 = E7dE11 = E9fE13 = E11hE14 = E13jE16 = E7k

Define the following “alphabet”

Set up a system of Regular Equations

Solution for Paths = E16 + E14

E16 = ab*c[d ( e + f (g + hib*c)) ]*kE14 = ab*c[d ( e + f (g + hib*c)) ]*dfhjPaths = ab*c[d ( e + f (g + hib*c)) ]* (k+dfhj)

Page 50: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 50

Expression => Code

{ boolean X; 1;3; //a (2 = true) while( 4 ) { 5; 3 } //b* 6; //c X := true; // Boolean variable for exception handling while ( X and 7 ) { //7T 8; //d if( 9 ) { //9T 10; 15 //e } else { //9F = f if( 11 ) { //11T 12;15 //g else{ //h if( 13 ) { //13T 5; 3 //i while( 4 ) { 5; 3} //b* 6; //c = (4F)6 } else X = false; //13F = exception condition }//11 - else }//9 - else }// while(7 and X) if( not X ) throw(exception); //j = abnormal end } //k = normal end

Equivalent Structured Code

a = 123b = (4T)523c = (4F)6d = (7T)8e = (9T)(10)(15)f = (9F)g = (11T)(12)(15)h = (11F)i = (13T523)j = (13F)k = (7F)

Solution for Paths = E16 + E14

E16 = ab*c[d ( e + f (g + hib*c)) ]*kE14 = ab*c[d ( e + f (g + hib*c)) ]*dfhjPaths = ab*c[d ( e + f (g + hib*c)) ]* (k+dfhj)

Page 51: Software Unit Testing Case Study:

October 2, 2006 (c) Dr. David A. Workman 51

Summary & Conclusion

• Summary (What are the main points?)– DFAs and REs are more than just (equivalent) mathematical specifications for

Regular Languages and algorithms for lexical analysis, they are useful for modeling algorithms of any kind and complexity.

– Using algorithms for equivalence between DFAs and REs we were able to see why Bohm and Jacopini’s theorem is true, and why Dijkstra so strongly endorced the principles of structured programming.

• Conclusion (What have we learned?) The “marriage” between Theory and Practice is not “on the rocks”, this couple is

not “legally separated” or “divorced” with “irreconcilable differences,” they are a harmonious couple, inextricably entwined, cooperating and complementing each other. What mathematics has brought together, let no computer scientist put asunder!