Reading & Writing Objects
+ we can write objects to a file without having to connect them to things like strings
+ we can read objects from a file without having to convert strings to objects
Serialization means:
+ save a file the class & the data in the instances of that class
+ if any fields reference other objects those will be serialized, too
+ when reading from a file where the objects were serialized they will be stored to same state and content they had when serialized
package java.util;
public class Date implements java.io.serializable {...}
...
// create a file
FileOut.printStream fos = new FileOutputStream("serialDate.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//create data object and write to file
Date d = new Date();
oos.writeObject(d);
this allows us save an object of type Date to file
Ex: read object from file
FileInputStream fis = new FileInputStream("serialDate.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
Object o = ois.readObject(ois); //reads Object from the object input stream (returns from stream)
// now we need to typecast the object to Date (the type you expect)
Date savedDate =(Date)o;
Type casting is type safe in Java, i.e. you can't force an object into a class it doesn't belong to
If you try to...it will raise a "class cast exception"
EX:
Object o = ois.readObject(ois);
Cup myCup = (Cup)o; //this is wrong - raises a class cast exception
Note: if a class is serializable, then all of its classes are serializable as well.
Serialization and Security
The people designing java debated whether all objects shoul dbe serializable
+ the programmer must explicitly decide what objects are serializable because it has implications on security
EX: assume you serialize a file descriptor. Then somebody evil edits the file where the object is stored and modifies it. When the object is read from the file, the file descriptor will point to someplace other than intended
NOTE: you must consider the security implications of your decision to make a class serializable
What can you do?
+ validate the object after you read it back; cross-check for consistency
+ take care of serialization yourself; implement the Externalizable interface (provide the implementation for the read and write methods)
+ use the keyword "transient" to prevent certain data members from being written to the file
class Employer {
String name;
int employeeID;
private transient int SSN;
//the social security # will not be written to the file
//when an instance of Employee is serialized
...
}
Certain classes cannot be serialized at all, e.g. java.lang.Thread
+ thread include java code and native code (perhaps written in C/C++); threads maintain two stacks, one for Java code, the other for native code; the problem is that Java doesn't know what
's in the native stack, therefore serialization cannot possibly work
Assertions and Defensive Programming
+ defensive programming is a way to mitigate the effects of bugs w/o knoowing where the bugs are
NOTE: adopting a defensive programming attitude does not mean youre incompetent
How does it work?
_ figure out invariants, i.e. conditions you expect to hold true at certain points in the program. Test if the condition actually holds true; if it doesn't then something is really wrong -> abort
EX: assume you are working on a compiler, big sofwatre lots of possibiliteis for stuff to go wrong
class Symbols {
Vector symbols;
Vector types;
Vector partitions;
}
Assume a symbol called "sym", the sumbol vector. To find the Type of "sym" we need to access the Types of vecotr at the same index.
int i = symbols.indexOf(sym);
Type t = types.get(i);
This code only works if the vectors symbols and types have the same length
this is your invariate for this piece of code.
Runtime Assertions
+ don't use assertiona as a crutch for sloppy/bad code
+ ways to use assertions
-at the start of precedure to check that procedure is called as ecpected (e.g. proper value for assigments, etc.)
- at the end of the procedure to check that result is reasonable/plausible
- when an operation is performed that has an external effect
Assertions in Java
+ introduced in Java 1.4
EX:
assert booleanExpression ;
+ assert is not recognized by the java compiler unless you instruct it to;
java -source 1.4 MyClass.java
you'll get compilation error with this flag (-source) if your program contains assert statements
+ assertions are turned off by default: you must instruct the run-time environment to execture them
java -ea MyClass
NOTE: test your program both with assertions enabled and assertions disabled (they should do the exact same thing)
avoid assertions that have side effects
EX:
boolean noMoreData = true;
boolean checkingMethod() {
noMoreData = false;
return noMoreData;
}
PROBLEM: different values for noMOreData depending on whether assertions are enabled or disabled.
Q: what is the status of your code?
A: (typical): I'm X% done (x is typically 80 or 90%)
WRONG! you may be 90% done for another month or year even thought waht you've done took only a week or a day...it's easy to get stuck
The correct answer is I'm done or I'm not done.... DO NOT give any other answer (make promises you cannot keep)
Thursday, April 19, 2007
Friday, April 13, 2007
4/12 Testing
Samel test for you project
$ java InventoryProject
> user Alice ( user perforimgn command .. a new user is specificied) > role Operations (role of current user) > add-inv ( "add inventory" command . . . > show-user
> Alice
> show-role
> Operations
.
.
> quit
$
NOTE: Instead of having mulitple "show -" commands we culd have just one that takes an argument that indicates what to show
ex:
show -user
show -group
show -available
show -booked
.
.
.
if number of records is small, you can sum "view total"
if number of records exceeds ~1000, you may want to start keeping a running summary, but this makes updating harder, but it makes a summary easier
view booked command needs to iterate thru the store and sum booked inventory
**************************
Testing
black-box (aka functional testing)
+ based on specifications - no inspection
+ avoids the mistake of examining/inspecting the app and making the same wrong assumptions the developers made
-independent verification of functionality
+tests are representation independent
NOTE: this is how the TA is going to test your project. the other part of the grading is code inspection
Clear-Box (aka white-box)
+ test cases are generated by looking at the implementation
+ very effective n pointing out problems with inputs that are handled differently by different branches in the code
EX:
int max3(int x, int y, int z) {
if (x>y) {
if (x>y) return x; else return z;
} else {
if (y>z) return y; else return z;
}
}
Clear-box testing also helps finding additional test condition based on things like local variable, loopiterators, etc.
EX:
possible addtional test case
+ input such that the loop is never exectured
+ execeuted just once
+ executed max number of times
Test Strategy and automation use both black=box and clear box testing
(ideally, the test cases developed by someobdy whos only read the specification for the product)
bottom-up : test each module before it gets integrated into the larger context
top-down test hte application until all test pass
assume the followng module dependency diagram
A
| |
B C
| |
D | |
E F
bottum up : test D before B
test E & F before C
test B & C before A
Q: how do you test D before B?
A: youll need to dvlop drivers/wrappers that provide the inputs needed by D.
top down:write stubs to stimulate the behavrior of those parts of the system that havent been developed yet
write stubs..all tests fail..work on it till it passes
as you start writing more code, you change those stubs in to actual working code
advantage of top-down: erros can be identified early in the process before all code has been written
top down is difficult for a large project because clients are unable to detail all criteria for the application
regression testing
+ test your code after youmake code change
- validate that you havent introduced a defect while fixing some code or adding new functionality
automated acceptance testing
+ the test can record human's actions on screen
+ add custom scripting to supplement the recording
The tool can do what a human would do in front of the same screen (e.g. fill in text bozes, check radio buttions, submit forms, etc.)
NOTE: the development of test scrpting should be treated like any other software development activity.
testing is like code, it's intellectual property... will help manage employee turnover, gaurantee function and customer satisfaction, maintain sofware, ...
"start writing code and see how it evolves"
$ java InventoryProject
> user Alice ( user perforimgn command .. a new user is specificied) > role Operations (role of current user) > add-inv ( "add inventory" command . . . > show-user
> Alice
> show-role
> Operations
.
.
> quit
$
NOTE: Instead of having mulitple "show -" commands we culd have just one that takes an argument that indicates what to show
ex:
show -user
show -group
show -available
show -booked
.
.
.
if number of records is small, you can sum "view total"
if number of records exceeds ~1000, you may want to start keeping a running summary, but this makes updating harder, but it makes a summary easier
view booked command needs to iterate thru the store and sum booked inventory
**************************
Testing
black-box (aka functional testing)
+ based on specifications - no inspection
+ avoids the mistake of examining/inspecting the app and making the same wrong assumptions the developers made
-independent verification of functionality
+tests are representation independent
NOTE: this is how the TA is going to test your project. the other part of the grading is code inspection
Clear-Box (aka white-box)
+ test cases are generated by looking at the implementation
+ very effective n pointing out problems with inputs that are handled differently by different branches in the code
EX:
int max3(int x, int y, int z) {
if (x>y) {
if (x>y) return x; else return z;
} else {
if (y>z) return y; else return z;
}
}
Clear-box testing also helps finding additional test condition based on things like local variable, loopiterators, etc.
EX:
possible addtional test case
+ input such that the loop is never exectured
+ execeuted just once
+ executed max number of times
Test Strategy and automation use both black=box and clear box testing
(ideally, the test cases developed by someobdy whos only read the specification for the product)
bottom-up : test each module before it gets integrated into the larger context
top-down test hte application until all test pass
assume the followng module dependency diagram
A
| |
B C
| |
D | |
E F
bottum up : test D before B
test E & F before C
test B & C before A
Q: how do you test D before B?
A: youll need to dvlop drivers/wrappers that provide the inputs needed by D.
top down:write stubs to stimulate the behavrior of those parts of the system that havent been developed yet
write stubs..all tests fail..work on it till it passes
as you start writing more code, you change those stubs in to actual working code
advantage of top-down: erros can be identified early in the process before all code has been written
top down is difficult for a large project because clients are unable to detail all criteria for the application
regression testing
+ test your code after youmake code change
- validate that you havent introduced a defect while fixing some code or adding new functionality
automated acceptance testing
+ the test can record human's actions on screen
+ add custom scripting to supplement the recording
The tool can do what a human would do in front of the same screen (e.g. fill in text bozes, check radio buttions, submit forms, etc.)
NOTE: the development of test scrpting should be treated like any other software development activity.
testing is like code, it's intellectual property... will help manage employee turnover, gaurantee function and customer satisfaction, maintain sofware, ...
"start writing code and see how it evolves"
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
$
-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
$
Subscribe to:
Posts (Atom)