Thursday, April 5, 2007

April 5, streams , testing and project testing

project checkpoint is today
-submit on blackboard
+ the code you've developed so far
+ a quick/short description of where you are with the project

today:
+ stream I/O
+ Testing
+ Acceptance testing for your project


Stream I/O

Q: Where does stream input come from (or go) ?
A:
+Files
+ terminal window
+network connections
+ audio, video,
+ printers, and other devices
+ pipes (way to do interprocess communication
EX:
$ ls | wc -l
the output of one command (ls) is piped (|) to another command (wc , word count)


Stream Semantics
there are 4 basic operations supported on stream (you should find them in any implementation)
1) open
stream = open(device or file name);
+create a new stream -OR-error thrown if stream cannot be opened

2) close
close(stream);
+closes the given stream; no longer available for reading/writing

3) read
num = read(byte[] buf, int nbytes, Stream stream);
+reads up to nbytes bytes from the stream into buf
+ returns the number of bytes actually read
+read data is removed from the stream, the next read will get different data

4) write
num = write(byte[] buf, int nbytes, Stream stream);
+ writes up to bytes nbytes of data from buf to the stream
+ returns number of bytes actually written

blocking
usually read doesn't return every character, usually you wait for a line or so
read() waiting for some input to appear before returning
EX: read from keyboard before user has hit any key, or from network before any packet has arrived

NOTE: write(), open(), close() can also block , though typically when dealing when dealing with network connections, other program, etc (things outside your environment)

NOTE: sometimes we don't want blocking because it may get entire application stuck. Most stream implementations provide a way to find if there is any data in the stream
EX: in Java call available()

Buffering
reading one byte at a time is expensive and slow --> read data in large chunks that will minimize the (per byte) overhead
+ "buffered" read and write

NOTE: in JAVA buffering is explicit (have to create a buffer, otherwise its one byte at a time)

JAVA
byte-oriented I/O
+ InputStream and OutputStream are two big (decoroator) classes
+ one byte at a time

character-oriented I/O (Unicode compliant)
+ a character in JAVA is two bytes
+ Reader and Writer (are two big (decorator) classes)

Testing
unit testing will test that a specific method in a class will do what you think it should do
but when you put together multiple components into software, how do you know that the final product will actually do what the user wants?

+Goal: ensure that the application works properly
+Testing cannot prove the absence of errors, only their presence
- through testing we can increase our confidence in the application, assume by testing the application that errors will be found



3 techniques to verify a program
1) prove correctness ; through formal specifications (preconditions, post -conditions, loop invariants, etc.)
+ it's impractical, people don't use it for real applications, it just doesn't work cuz it's too complicated.
+ does not solve the fact that specification is incorrect

2) run the program on all possible inputs
+ infeasible due to the large number of possible combinations of inputs
EX: assume a program written in JAVA that takes three 'int' as inputs.
Q: how many possible combinations of inputs are there?
int is 32 bits, so 2^32 possible integers
A: (2^32)^3 = 2^96 ~ 8*10^28

Q: assuming you test 10^6 combinations per second?
A: 8*10^22
86,000 sec/day ~ 100,000 sec /day
so ~ 8*10^17 days = HUGE!

3) run the program on a subset of all possible inputs
+ doesn't gaurantee correctness
+ partition the space of all possible inputs in equivalence classes; any member in each equivalence class is equivalent to any other

EX: the realation hasSameGradeAs on the set of stduents in this class is an eq uivalence relation (i.e. reflexive, symmetric and transitive)

insteadof doing a mathematically crroect partitioning of the set of inputes well use hearuistics
and hope that at least one test case derive through heuristics maps to oone of the unknowable equivalence classes

guess equivalence classes
add additional test cases to account for potential problems related to our guess

Heustics

1) Coverage: find test cases that will exercise each code or specification construct

EX: Java app that takes one 'int' as input. How do youpartition the input space?

2) Boundary cases: include values at the extremities of the range

3) Duplicates: programs often behave differently when there inputs have particular relationships to each other.

EX: an airline bookingsystem a non-stop flight w the same origin and destination (e.g ORD-ORD)


NOTE: the three heuristic should be applied to
+ input values
+ output values
+ nonexplicit values (e.g. loop iterations, set size, number of occurrences of a specific argument)

NOTE: When multiple heuristics apply you should take their cross-product
EX: one heuristic suggest two partitions over one input and another heuristic 3 partitions over another input, then your test untits should have at least 2*3=6 test cases

NOTE: the heuristic can be applied to
+ black box testing -- based on specificiations only; have no idea how it's been built
+ clear box tsting (aka white-box testing) -- you know how its been built



III. Testing your project

NOTE: missing throughout this example is name/role of user
e.g. Mike-Sales, Virgil-President

Prof: I'll give you a set of test cases to use, such as...

add-section "sports"
add-section "news"
add-subsection "news" "local"
add-subsection "news" " national"
list section
(prints) > "sports", "news"

add-inv "news" "local" "300x250" 7/15/2007 100000
add-inv "news" "local" "300x250" 7/15/2007 500000
list-inv "news" "local" "300x250" 7/15/2007
(prints) > 1500000 //total inventory for this section,sub,placement, date

list-inv-avail "news" "local" "300x250" 7/15/2007
(prints)> 1500000 //since i havent booked any yet

book-inv "news" "local" "300x250" 7/15/2007 600000
list-inv-avail "news" "local" "300x250" 7/15/2007
(prints)> 900000 //what's left after i booked 600000
book-inv "news" "local" "300x250" 7/15/20007
(prints)> get lost dude, i dont have this much inventory!
(prints)> Error: only 100000 impressions available


This can be implemented in a number of ways.
(i) one class for each command
EX: java add-section "sports"
NOTE: jave doesn't allow "-" in class name, so use addSection

NOTE: the only way to maintain state between commands is to make sure you write objects to a file or database (otherwise there is no history of command) make sure all objects are serializable. when a command is executed it starts be reading from the file/db.


(ii) implement a command processor
+ read command from std-in (standard input)
+ parse command
+ delegate execution to class method
+ return results

in this case, you only need to save the state once, when the "quit" command is executed.

EX:

$ java InventorySystem
add-inv #waiting for command to be typed
...
...
...
quit
"good bye" # will save state in file/db
$

No comments: