350 likes | 356 Views
Introduction to Error Handling, SUnit, Blackbox Testing, and Refactoring. CS2340 Summer 2004. Exception Handling in Squeak. Class Exception and its subclasses provided for use. Can emulate try/catch block in other languages
E N D
Introduction to Error Handling, SUnit, Blackbox Testing, and Refactoring CS2340 Summer 2004
Exception Handling in Squeak • Class Exception and its subclasses provided for use. • Can emulate try/catch block in other languages • Exceptions pass up inheritance hierarchy. If not handled, get default handler at Object.
Example | x y | x:=7. y:=0. [x / y] “like a try block” on: ZeroDivide “exception class” do: [ :exception | Transcript show: exception description ; cr. 0 ].
Example | f | [f:=FileStream fileNamed: 'fred'. f nextPutAll: 'Test'. f close. ] on: FileDoesNotExistException do: [:exception | Transcript show: exception description. ].
Blackbox Testing • Going to get the theory from 2335 • Treat code as a blackbox • Base test cases on specification • Two major techniques: • Equivalence Partitions • Boundary Value Tests • Exhaustive testing not possible
Equivalence Partitions • Treat sets of data as same (if one test succeeds all tests succeed) • For ranges, pick one test in range, one test on each end. • For sets, pick one in set, one not in set. • For unique values, pick value, not value.
Examples • Must accept years between 1-2050. Test cases: 0, 1876 , 2076. • Passwords must be 6-8 chars long: Test cases: ab, abcdef, abcdegujswidn • Leap years are divisible by four: Test cases: 16, 99 • Phone exchanges must not begin with 555. Test cases: 555, 498
Boundary Value Tests • Most of the errors happen on the boundaries between sets • Must accept years between 1-2050. • Test cases: 0, 1, 2050, 2051. • Boundary Value Tests complements Equivalence Partitions
Writing your tests • We could just write workspace code and DoIt over and over… • Hoping that we don’t ever close window • Checking transcript manually to ensure results are what we want. • We could write a custom class to do our test and result checking • We can use the SUnit framework.
SUnit • Testing framework for creating and running unit tests (regression tests) automatically in Smalltalk • Originally developed by Kent Beck • Implementations exist for many languages • JUnit for Java
SUnit Advantages • Self-checking and reporting • Check results against expected results • Report which test is broken • Built-in initialize before a test and clean-up after a test • setUp is called before each method test • tearDown is called after each method test
When to use SUnit? • Extreme Programming • Create unit test before the code • Helps you understand what the code must do • Helps you to know when the code is done • Used for regression testing • Did you break anything when making changes? • Maintenance • Once you find a bug create a unit test to make sure it is fixed and stays fixed
Using SUnit • Derive class from TestCase • Do any set up (initialize variables) in setUp • Do any clean up in tearDown • Create methods testXxxx • Use: • self assert: expr_that_evals_true • self deny: expr_that_evals_false • self should: [ block that evals to true ]. • self shouldnt: [block that evals to false ]. • TestRunner open.
Example: Assume we have a class Muppet with method: name: aName name:=aName. ^name. And: name ^name. testName | oscar | oscar := Muppet new. oscar name: 'oscar'. self assert: oscar name = 'Oscar'. self should: [oscar name = 'Oscar']. self deny: oscar name = 'Ocsar'. TestCase subclass: #TestMuppet instanceVariableNames: ‘ ‘ classVariableNames: ‘ ‘ poolDictionaries: ‘ ‘ category: ‘Muppet Classes’ .
Key steps • For each ‘real’ class X, have a test class TestX derived from TestCase • Decide how to test functionality • For functionality Y in class X, have a test method testY in class TestX. • Run TestRunner to evaluate tests automatically (TestRunner open) • May use SqueakMap to download TestBrowser if desired (more later)
Testing with Exceptions • Check for exceptions • self should: [boolean] raise: Exception • Make sure no exceptions • self shouldnt: [boolean] raise: Exception
Refactoring • Improving the design • To make it cheaper and easier to maintain • Without adding functionality • Change the current code to improve it • Use unit tests to make sure it still works • Key part of Extreme Programming • Evolve the design • Key to Maintenance • Fix the “ugly” stuff
Book • Refactoring, Improving the Design of Existing Code • By Martin Fowler • ISBN 0-201-48567-2 • Uses Java • But ideas can be used for any language
Why don’t People Refactor? • Doesn’t add functionality • No cool new feature to show off • People don’t want to pay for it • Afraid of breaking things that work • Reduce this fear by unit tests • Afraid of opening a can of worms • Changing A leads to changing B, C, D, etc.
What if you Don’t? • Code complexity grows • Changes are harder to make • Probability of error increases • Code gets written to “get around” problems • Harder for new people to understand • Code gets duplicated
Refactoring Goal • Anybody can write code that a computer can read • Good programmers write code that other humans can understand
What makes code hard to read and maintain? • Bad names (i, aValue, str) • Good names: arrayIndex, listSize, name • Magic numbers (255, 32767) • Long methods (contain lots o’ code) • Things that don’t make sense • Methods in the wrong place • Attributes in the wrong place • Duplicating things • And much more …
Extract class • Example: class Person has lots of stuff in it (name, credit card stuff, contact info etc) • Problem: Class gets big and hard to understand • Solution: Pull out related attributes and make a class (like CreditCard)
Extract Method • Problem: class has a long method that is hard to understand • Solution: break the method up into more understandable parts
Extract Method Process • Pull out any duplicated code and make that a method • Pull out cohesive pieces and make methods for each piece • Be sure to move local variables as needed • Pass some variables as parameters • Modify the original method to call the piece methods
Move Method • Example: Clock formatting time • Problem: a method exists on a class but uses data found in another class • Solution: move the method to the class that has the data the method works on
Move Attribute • Example: SlideShow has a fileDirectory • Problem: Class has an attribute that it shouldn’t have • Solution: Move the attribute to the class that should have it • Use delegation to access from other classes
Replace Conditional with Polymorphism • Example: Drawing Editor with Shape attribute • Constants for Circle, Rectangle, Triangle • Draw code checks type and then does correct drawing • Problem: conditional on constant is hard to extend • Solution: create subclasses Circle, Rectangle, Triangle and each overrides an abstract draw method in Shape
SqueakMap • Software package distribution mechanism with Squeak • http://coweb.cc.gatech.edu/cs2340/1407 • http://minnow.cc.gatech.edu/squeak/2726 • World Menu -> Open… -> Package Loader • Asks if you want to install SqueakMap; say yes • Eventually fires up SM Package Loader
Package Loader • Select “TestBrowser” in SqueakMap • Right-click, choose “install” from menu
TestBrowser • TestBrowser open
Next on the Menu • Read chapter 3 • “Joe the Box” – simple 2D graphics • Milestone 1 due next Tuesday! • Quiz 1 on Tuesday