Sie sind auf Seite 1von 21

Lecture 8: Program Testing

Associations, Data transfer objects Program testing/debugging Program inspection

Layered architecture G ! "#amp$e


Tkinter is the most commonly used GUI toolkit for Python (available on most Unix platforms, as well as on Windows and acintosh systems !

"eview #tudent$"U% application with GUI

Tkinter (or any other python GUI toolkit! is not a re&uirement for the exam

Associations
In real life, there are lots of many'to'many associations In a software these (eneral associations complicate implementation and maintenance bidirectional association means that both ob)ects can be understood only to(ether It is important to constrain relationships as much as possible* Imposin( a traversal direction +ddin( a &ualifier, reduce multiplicity ,liminatin( nonessential associations

Associations %ata$og e#amp$e

gr = ctr.assign("1", "FP", 10) assert gr.getDiscipline()=="FP" assert gr.getGrade()==10 assert gr.getStudent().getId()=="1" assert gr.getStudent().getName()=="Ion"

st = Student("1", "Ion", Address("Adr", 1, "Cluj")) rep = GradeRepository() grades = rep.getAll(st) assert grades 0!.getStudent()==st assert grades 0!.getGrade()==10

%$ient %ode !gnores &epository !mp$ementation' De(e$opers Do )ot

de" store(self, """ Store post: raise

gr)#

a grade grade is in the repository GradeAlreadyAssigned exception if we already ha e a grade for the student at the gi en discipline raise !epository"xception if there is an I# error when writing to the file """ i" self."ind(gr.getStudent(), gr.getDiscipline())$=None# raise GradeAlreadyAssigned() %open t&e "ile "or append try# " = open(self.''"name, "a") grStr = gr.getStudent().getId()("$"(gr.getDiscipline() grStr =grStr("$"(str(gr.getGrade())("%n" ".)rite(grStr) ".close() e*cept I+,rror# raise Repositor,*ception("&na'le to write a grade to the file")

Data transfer objects -unctionality* #how the best . students at a (iven discipline/ #how a table containin( the name of the student and his (rade at the disicipline

$reate a new class that contains )ust the needed information to implement the re&uested functionality

Program testing
Testing is observin( the behavior of a pro(ram in many executions/ ,xecute the pro(ram for some input data and observe if the results are correct for these inputs/ Testin( does not prove pro(ram correctness (only (ive us some confidence!/ 0n the contrary, it may prove its incorrectness if one execution (ive wron( results/ Testin( can never completely identify all the defects within software/

Testing methods
"#hausti(e testing
$heck the pro(ram for all possible inputs/ Impractical so we need to choose a finite number of test cases/

*$ac+ bo# testing


The selection of input data for testin( is decided by analy1in( the specification/ %istinct cases of the problem are decided and we use a test input data for each case

,hite bo# testing


#elect the test data by analy1in( the text of the pro(ram/ We select test data such that all the execution paths are covered/ We test a function such that each statement is executed/

,hite bo# (s *$ac+ *o# testing


de" isPrime(nr)# """ (erify if a nu)'er is pri)e return *rue if nr is pri)e False if not raise (alue"rror if nr+,""" i" nr-=0# raise .alue,rror("nr need to 'e positi e") i" nr==1#%1 is not a prime num/er return 0alse i" nr-=1# return 2rue "or i in range(3,nr)# i" nr4i==0# return 0alse return 2rue

2lack 2ox test case for a prime3not prime test case for 4 test case for ne(ative number

White 2ox (cover all the paths! test case for 4 test case fot ne(ative test case for 5 test case 6 test case for prime (no divider! test case for not prime
de" whiteBoxPrimeTest()# assert (is5rime(1)==0alse) assert (is5rime(1)==2rue) assert (is5rime(11)==2rue) assert (is5rime(7)==2rue) try# is5rime(83) assert 0alse e*cept .alue,rror# assert 2rue try# is5rime(0) assert 0alse e*cept .alue,rror# assert 2rue

de" blackBoxPrimeTest()# assert (is5rime(6)==2rue) assert (is5rime(7)==0alse) try# is5rime(83) assert 0alse e*cept .alue,rror# assert 2rue try# is5rime(0) assert 0alse e*cept .alue,rror# assert 2rue

Testing $e(e$s
Tests are fre&uently (rouped by where they are added in the software development process, or by the level of specificity of the test/

nit testing
Unit testin( refers to tests that verify the functionality of a specific section of code, usually at the function level/
Testin( unit of code in isolation (functions!/ Test small parts of the pro(ram independently

!ntegration testing
$onsiders the way pro(ram works as a whole/ +fter all modules have been tested and corrected we need to verify the overall behavior of the pro(ram/

Automated testing
Test automation is the process of writin( a computer pro(ram to do testin( that would otherwise need to be done manually/ use of software to control the execution of tests, the comparison of actual outcomes to predicted outcomes, the settin( up of test preconditions

TDD:
T%% #teps* 7 7 7 automated test cases writin( specification (inv, pre3post! 8 throwin( or not exceptions production code

Python unit testing frame-or+ .Py nit/


unittest module supports* test automation sharin( of setup and shutdown code for tests a((re(ation of tests into collections independence of the tests from the reportin( framework
import unittest class TestCase(unittest.2est9ase)# de" setUp(self)# %code e*ecuted /e"ore e:ery test;et&od :al=Student.alidator() self.ctr=Student9ontroller(:al, StudentRepository()) st = self.ctr.create("1", "Ion", "Adr", 1, "Cluj") de" tearDown(self)# %cleanup code e*ecuted a"ter e:ery test;et&od de" testCreate(self)# self.assertTrue(self.ctr.getNrStudents()==1) %test "or an in:alid student self.assertRaises(.alidation,*,self.ctr.create,"1", "", "", 1, "Cj") %test "or duplicated id self.assertRaises(DuplicatedID,*ception,self.ctr.create,"1", "I", "A", 1, "j") de" testRemove(self)# %test "or an in:alid id self.assertRaises(.alue,rror,self.ctr.remo:e,".") self.assert2rue(self.ctr.getNrStudents()==1) st = self.ctr.remo:e("1") self.assert2rue(self.ctr.getNrStudents()==0) self.assertEquals(st.getId(),"1") self.assert2rue(st.getName()=="Ion") self.assert2rue(st.getAdr().getStreet()=="Adr")

i" ''name'' == /00)ain00/# unittest.main()

Debugging
Debugging is the activity that must be performed when testin( indicates the presence of errors, to find errors, and rewrite the pro(ram with the purpose of eliminatin( the errors/ 7 usin( print statement 7 usin( I%, %ebu((in( is the most unpleasant activity/ %ebu((in( must be a(oided0
"c$ipse debug perspecti(e

Debug (ie wiew the current execution trace (stack trace! execute step by step, resume3pause execution 1ariab$es (ie view variable values

Program inspection
+ny fool can write code that a computer can understand/ Good pro(rammers write code that humans can understand Pro(rammin( style consist of all the activities made by a pro(rammer for producin( products easy to read, and easy to understand, and the way in which these &ualities are achieved

%oding sty$e .c$asses, functions/


"eadability is considered the main attribute of style/ + pro(ram, like any publication, is a text must be read and understand by another pro(rammer/ The element of codin( style are* 7 comments 7 text formattin( (indentation, white spaces! 7 specification 7 (ood names for entities (classes, functions, variables! of the pro(ram 8 meanin(ful names 8 use namin( conventions

)aming con(entions:
7 7 7 7 class names* #tudent, #tudent"epository variable names* student, nr,lem (nr9elem! function names* (et:ame, (et+ddress, store#tudent ((et9name,(et9address, store9student! constants* +;

Whatever convention you use, use them consistent$y/

&efactoring
"efactorin( is the process of chan(in( the software system in such a way that it does not alter the external behavior of the code yet improves its internal structure/ It is a disciplined way to clean up the code that minimi1es the chances of introducin( bu(s/ When you need to add a new feature to the pro(ram, and the pro(ram<s code is not structured in a convenient way for addin( the new feature, first refactor the code to make it easy to add a feature, then add the feature

,hy to refactor
7 7 7 7 "efactorin( improves the desi(n of the software "efactorin( makes software easier to understand "efactorin( helps you find bu(s "efactorin( helps you pro(ram faster

*ad sme$$s
When we need to refactor the code

Dup$icated code Long method Large c$ass Long parameter $ist %omments Di(ergent change
0ne class is commonly chan(ed in different ways for different reasons

&efactoring 2 3ethods
&ename 3ethod
The name of a method does not reveal its purpose.

%onso$idate %onditiona$ "#pression


=ou have a se&uence of conditional tests with the same result/ $ombine them into a sin(le conditional expression and extract it/

%onso$idate Dup$icate %onditiona$ 4ragments


The same fra(ment of code is in all branches of a conditional expression/ ove it outside of the expression/

Decompose %onditiona$
=ou have a complicated conditional (if'then'else! statement/ ,xtract methods from the condition, then part, and else parts/

!n$ine Temp
You have a temp that is assigned to once with a simple expression, and the temp is getting in the way of other refactorings. &ep$ace a$$ references to that temp -ith the e#pression0

!ntroduce "#p$aining 1ariab$e


You have a complicated expression. Put the resu$t of the e#pression, or parts of the e#pression, in a temporary (ariab$e -ith a name that e#p$ains the purpose0

&efactoring 2 3ethods
&emo(e Assignments to Parameters
The code assigns to a parameter. se a temporary (ariab$e instead0

&emo(e %ontro$ 4$ag


You have a variable that is acting as a control flag for a series of boolean expressions. se a brea+ or return instead0

&emo(e Doub$e )egati(e


You have a double negative conditional. 3a+e it a sing$e positi(e conditiona$

&ep$ace )ested %onditiona$ -ith Guard %$auses


A method has conditional behavior that does not make clear what the normal path of execution is se Guard %$auses for a$$ the specia$ cases

&ep$ace Temp -ith 5uery


You are using a temporary variable to hold the result of an expression. "#tract the e#pression into a method0 &ep$ace a$$ references to the temp -ith the e#pression0 The ne- method can then be used in other methods0

&efactoring 2 %$ass
"ncapsu$ate 4ie$d
There is a public field. 3a+e it pri(ate and pro(ide accessors0

&ep$ace 3agic )umber -ith 6ymbo$ic %onstant


You have a literal number with a particular meaning. %reate a constant, name it after the meaning, and rep$ace the number -ith it0

"#tract 3ethod
You have a code fragment that can be grouped together. Turn the fragment into a method -hose name e#p$ains the purpose of the method0

3o(e 3ethod
A method is, or will be, using or used by more features of another class than the class on which it is defined. %reate a ne- method -ith a simi$ar body in the c$ass it uses most0 "ither turn the o$d method into a simp$e de$egation, or remo(e it a$together0

3o(e 4ie$d
A field is, or will be, used by another class more than the class on which it is defined. %reate a ne- fie$d in the target c$ass, and change a$$ its users0

Das könnte Ihnen auch gefallen