3-OOP in Java - Version 1.0 - 2016-12-01
3-OOP in Java - Version 1.0 - 2016-12-01
Contents
• Introduction to Java
• Object-Oriented Programming in Java
• Specification and Testing
1
Contents
• Introduction to Java
• Object-Oriented Programming in Java
– Object-oriented programming basics
– Information hiding
– Exceptions
• Specification and Testing
Contents
• Introduction to Java
• Object-Oriented Programming in Java
– Object-oriented programming basics
– Information hiding
– Exceptions
• Specification and Testing
2
Objects
Classes
3
Class example – complex numbers
class Complex {
private double re; // Real Part
private double im; // Imaginary Part
public Complex(double re, double im) {
this.re = re;
this.im = im;
}
public double realPart() { return re; }
public double imaginaryPart() { return im; }
public double r() { return Math.sqrt(re * re + im * im); }
public double theta() { return Math.atan(im / re); }
public Complex plus(Complex c) {
return new Complex(re + c.re, im + c.im);
}
public Complex minus(Complex c) { ... }
public Complex times(Complex c) { ... }
public Complex divideby(Complex c) { ... }
}
4
Interfaces and implementations
5
Modifying class to use interface
class OrdinaryComplex implements Complex {
double re; // Real Part
double im; // Imaginary Part
public OrdinaryComplex(double re, double im) {
this.re = re;
this.im = im;
}
public double realPart() { return re; }
public double imaginaryPart() { return im; }
public double r() { return Math.sqrt(re * re + im * im); }
public double theta() { return Math.atan(im / re); }
public Complex plus(Complex c) {
return new OrdinaryComplex(re + c.realPart(), im + c.imaginaryPart());
}
public Complex minus(Complex c) { ... }
public Complex times(Complex c) { ... }
public Complex dividedby(Complex c) { ... }
}by
6
Interface permits multiple implementations
class PolarComplex implements Complex {
double r;
double theta;
public PolarComplex(double r, double theta) {
this.r = r;
this.theta = theta;
}
public double realPart() { return r * Math.cos(theta) ; }
public double imaginaryPart() { return r * Math.sin(theta) ; }
public double r() { return r; }
public double theta() { return theta; }
public Complex plus(Complex c) { ... } // Completely different impls
public Complex minus(Complex c) { ... }
public Complex times(Complex c) { ... }
public Complex dividedBy(Complex c) { ... }
}
7
Why multiple implementations?
• Different performance
– Choose implementation that works best for your use
• Different behavior
– Choose implementation that does what you want
– Behavior must comply with interface spec (“contract”)
• Often performance and behavior both vary
– Provides a functionality – performance tradeoff
– Example: HashSet, TreeSet
8
Contents
• Introduction to Java
• Object-Oriented Programming in Java
– Object-oriented programming basics
– Information hiding
– Exceptions
• Specification and Testing
Information hiding
9
Benefits of information hiding
10
Mandatory Information hiding
visibility modifiers for members
11
Controlling Access to Members of a Class
The following table shows where the members of the Alpha class are
visible for each of the access modifiers that can be applied to them
12
Discussion
13
Contents
• Introduction to Java
• Object-Oriented Programming in Java
– Object-oriented programming basics
– Information hiding
– Exceptions
• Specification and Testing
14
Compare to:
Exceptions
15
Control-flow of exceptions
• Checked exception
– Exception which are checked at Compile time called Checked
Exception
– Represent invalid conditions in areas outside the immediate
control of the program (invalid user input, database problems,
network outages, absent files)
– Must be caught or propagated, or program won’t compile
• Unchecked exception
– Unchecked Exception in Java is those Exceptions whose
handling is NOT verified during Compile time
– Represent defects in the program (bugs) - often invalid
arguments passed to a non-private method.
– Unchecked runtime exceptions represent conditions that,
generally speaking, reflect errors in your program's logic and
cannot be reasonably recovered from at run time
16
The exception hierarchy in Java
17
Design choice: checked and unchecked
exceptions and return values
• Unchecked exception
– Programming error, other unrecoverable failure
• Checked exception
– An error that every caller should be aware of and
handle
• Special return value (e.g., null from Map.get)
– Common but atypical result
• Do NOT use return codes
• NEVER return null to indicate a zero-length result
– Use a zero-length list or array instead
18
Benefits of exceptions
• Read more at
https://docs.oracle.com/javase/tutorial/essential/exceptio
ns/index.html
19
Guidelines for using exceptions (2)
20
The solution: try-with-resources
Automatically closes resources
try (DataInput dataInput =
new DataInputStream(new FileInputStream(fileName))) {
return dataInput.readInt();
} catch (FileNotFoundException e) {
System.out.println("Could not open file " + fileName);
} catch (IOException e) {
System.out.println("Couldn’t read file: " + e);
}
21
File copy with ARM
Contents
• Introduction to Java
• Object-Oriented Programming in Java
• Specification and Testing
– Specifying program behavior – contracts
– Testing correctness – Junit and friends
22
Contents
• Introduction to Java
• Object-Oriented Programming in Java
• Specification and Testing
– Specifying program behavior – contracts
– Testing correctness – Junit and friends
What is a contract?
23
Method contract details
Theoretical approach
• Advantages
– Runtime checks generated automatically
– Basis for formal verification
– Automatic analysis tools
• Disadvantages
– Requires a lot of work
– Impractical in the large
– Some aspects of behavior not amenable to formal specification
24
Textual specification - Javadoc
• Practical approach
• Document
– Every parameter
– Return value
– Every exception (checked and unchecked)
– What the method does, including
• Purpose
• Side effects
• Any thread safety issues
• Any performance issues
• Do not document implementation details
25
Contents
• Introduction to Java
• Object-Oriented Programming in Java
• Specification and Testing
– Specifying program behavior – contracts
– Testing correctness – Junit and friends
Semantic correctness
adherence to contracts
26
Formal verification
Testing
27
Manual testing?
Automate testing
28
Unit tests
JUnit
29
Selecting test cases: common strategies
• Read specification
• Write tests for
– Representative case
– Invalid cases
– Boundary conditions
• Write stress tests
– Automatically generate huge numbers of test cases
• Think like an attacker
– The tester’s goal is to find bugs!
• How many test should you write?
– Aim to cover the specification
– Work within time/money constraints
JUnit conventions
30
Testable code
31
Home work
JUnit
32
Test suites
• Obviously you have to test your code to get it working in the first
place
– You can do ad hoc testing (testing whatever occurs to you at the
moment), or
– You can build a test suite (a thorough set of tests that can be run at
any time)
• Disadvantages of writing a test suite
– It’s a lot of extra programming
• True—but use of a good test framework can help quite a bit
– You don’t have time to do all that extra work
• False—Experiments repeatedly show that test suites reduce debugging
time more than the amount spent building the test suite
• Advantages of having a test suite
– Your program will have many fewer bugs
– It will be a lot easier to maintain and modify your program
68 • This is a huge win for programs that, unlike class assignments, get actual
use!
33
XP approach to testing
• In the Extreme Programming approach,
– Tests are written before the code itself
– If code has no automated test case, it is assumed not to work
– A test framework is used so that automated testing can be done
after every small change to the code
• This may be as often as every 5 or 10 minutes
– If a bug is found after development, a test is created to keep the
bug from coming back
• Consequences
– Fewer bugs
– More maintainable code
– Continuous integration—During development, the program always
works—it may not do everything required, but what it does, it does
right
70
JUnit
34
Terminology
• A test fixture sets up the data (both objects and primitives)
that are needed to run tests
– Example: If you are testing code that updates an employee record,
you need an employee record to test it on
• A unit test is a test of a single class
• A test case tests the response of a single method to a
particular set of inputs
• A test suite is a collection of test cases
• A test runner is software that runs tests and reports results
72
35
Writing a JUnit test class, I
– Start by importing these JUnit 4 classes:
• import org.junit.*;
import static org.junit.Assert.*; // note static import
36
A simple example
• Suppose you have a class Arithmetic with methods int multiply(int x, int y), and
boolean isPositive(int x)
• import org.junit.*;
import static org.junit.Assert.*;
@Test
public void testMultiply() {
assertEquals(4, Arithmetic.multiply(2, 2));
assertEquals(-15, Arithmetic.multiply(3, -5));
}
@Test
public void testIsPositive() {
assertTrue(Arithmetic.isPositive(5));
assertFalse(Arithmetic.isPositive(-5));
assertFalse(Arithmetic.isPositive(0));
}
76}
Assert methods I
• Within a test,
– Call the method being tested and get the actual result
– Assert what the correct result should be with one of the assert methods
– These steps can be repeated as many times as necessary
37
Example: Counter class
• For the sake of example, we will create and test a trivial
“counter” class
– The constructor will create a counter and set it to zero
– The increment method will add one to the counter and return the
new value
– The decrement method will subtract one from the counter and
return the new value
• We write the test methods before we write the code
– This has the advantages described earlier
– However, we usually write the method stubs first, and let the IDE
generate the test method stubs
• Don’t be alarmed if, in this simple example, the JUnit tests
are more code than the class itself
78
@Before
void setUp() {
counter1 = new Counter(); // initialize the Counter here
}
38
The Counter class itself
Warning: equals
• You can compare primitives with ==
• Java has a method x.equals(y), for comparing objects
– This method works great for Strings and a few other Java classes
– For objects of classes that you create, you have to define equals
• assertEquals(expected, actual) uses == or equals
• To define equals for your own objects, define exactly this
method:
public boolean equals(Object obj) { ... }
– The argument must be of type Object, which isn’t what you want,
so you must cast it to the correct type (say, Person):
– public boolean equals(Object something) {
Person p = (Person)something;
return this.name == p.name; // test whatever you like here
}
• 81We’ll talk much more about equals later
39
Assert methods II
• assertEquals(expected, actual)
assertEquals(String message, expected, actual)
– expected and actual must be both objects or the same primitive
type
– For objects, uses your equals method, if you have defined it
properly, as described on the previous slide
82
• assertNotNull(Object object)
assertNotNull(String message, Object object)
– Asserts that the object is null
• fail()
fail(String message)
– Causes the test to fail and throw an AssertionFailedError
– Useful as a result of a complex test, when the other assert
methods aren’t quite what you want
83
40
Writing a JUnit test class, III
• This page is really only for expensive setup, such as when you
need to connect to a database to do your testing
– If you wish, you can declare one method to be executed just once, when
the class is first loaded
• @BeforeClass
public static void setUpClass() throws Exception {
// one-time initialization code
}
– If you wish, you can declare one method to be executed just once, to do
cleanup after all the tests have been completed
• @AfterClass
public static void tearDownClass() throws Exception {
// one-time cleanup code
}
84
41
Test-Driven Development (TDD)
• It is difficult to add JUnit tests to an existing program
– The program probably wasn’t written with testing in mind
• It’s actually better to write the tests before writing the code
you want to test
• This seems backward, but it really does work better:
– When tests are written first, you have a clearer idea what to do
when you write the methods
– Because the tests are written first, the methods are necessarily
written to be testable
– Writing tests first encourages you to write simpler, single-purpose
methods
– Because the methods will be called from more than one
environment (the “real” one, plus your test class), they tend to be
more independent of the environment
86
Stubs
42
Ignoring a test
88
Test suites
89
43
JUnit in Eclipse
• If you write your method stubs first (as on the previous slide), Eclipse
will generate test method stubs for you
• To add JUnit 4 to your project:
– Select a class in Eclipse
– Go to File New... JUnit Test Case
– Make sure New JUnit 4 test is selected
– Click where it says “Click here to add JUnit 4...”
– Close the window that appears
• To create a JUnit test class:
– Do steps 1 and 2 above, if you haven’t already
– Click Next>
– Use the checkboxes to decide which methods you want test cases for;
don’t select Object or anything under it
• I like to check “create tasks,” but that’s up to you
– Click Finish
• To run the tests:
90 – Choose Run Run As JUnit Test
This is how
This test passed long the
test took
Something is wrong
Depending on your
preferences, this
window might show
only failed tests
91
44
Recommended approach
The End
If you don't unit test then you aren't a software engineer, you
are a typist who understands a programming language.
--Moses Jones
--Andy Lester
93
45
THE END
46