1. Adding a feature
1.1. Test Driven Development
1.1.1. Write a failing test
1.1.2. Get it to compile
1.1.3. Make it pass
1.1.4. Remove Duplication
1.1.4.1. Refactor
1.1.5. Repeat
1.1.6. Legacy Addition
1.1.6.1. Get the class under test
1.2. Inheritance
1.2.1. Can be useful but use carefully
1.2.1.1. long term could cause confusion & need refactoring
1.2.1.2. Liskov substitution principle
1.2.1.2.1. A Rectangle != Square
1.2.1.2.2. Objects of subclasses should be substitutable for their parent class
1.2.2. Avoid overwriting concrete classes
1.2.2.1. if so, try to call super
2. Test Code
2.1. Not production code
2.1.1. Mock objects can break encapsulation if it makes testing easier
2.1.2. Try passing null
2.1.2.1. Worst case... exception
2.1.2.2. Maybe implement Null Object Pattern
2.1.2.2.1. This can be production code
3. Legacy
3.1. Dilema
3.1.1. When we change code - have tests, to add tests, I need to change code
3.2. Definition
3.2.1. Code Without Tests
4. Unit Tests
4.1. FAST!
4.2. Localize problems
4.2.1. quickly
4.3. NOT
4.3.1. touch database
4.3.2. Communicate across network
4.3.3. touch file system
4.3.4. require special environment config
4.3.5. Integration tests
5. Refactoring
5.1. Definition
5.1.1. Changes made to structure w/out changing behavior to make it easier to understand
5.2. Initially
5.2.1. Start Ugly
5.2.2. Surgery analogy
5.2.2.1. Scar left after
5.2.2.1.1. BUT
5.3. Legacy Code Change Algorithm
5.3.1. Identify Change Points
5.3.2. Find Test Points
5.3.3. Break Dependencies
5.3.3.1. interfaces
5.3.4. Write Tests
5.3.5. Make Changes & Refactor
6. Adding Behavior
6.1. Sprout Method
6.1.1. Put behavior in a new, distinct, testable method
6.1.2. Test this method even if/though caller is untested
6.1.3. Worst Case
6.1.3.1. Static method w/ arguments of intended class
6.1.3.1.1. This is a scar
6.1.3.1.2. Over time it will find a home
6.2. Sprout Class
6.2.1. When difficult to instantiate a class for testing
6.2.2. New class to do new behavior
6.2.3. Would NOT receive "Caller Class" (untested class where code was desired to be put in the first place)
6.2.3.1. Caller Class = Source Class
6.3. Wrap Method
6.3.1. Wrap source method with simpler delegating method
6.3.1.1. Or reuse method name & abstract original code
6.3.2. Decouple functionality from being shoved into the same method
6.3.3. Prevents temporal coupling
6.4. Wrap Class
6.4.1. Decorator Pattern
7. Testing takes too long?
7.1. When we don't test it takes too long
7.1.1. Compile Time
7.1.1.1. Entire project compilation
7.1.2. Deploy Time
7.1.3. Manual Verification
7.1.3.1. Multiple Times
7.2. Testing
7.2.1. Instantaneous feedback
7.2.2. Helps keep you in context & focused
7.2.3. Future guarantee of the feature with no additional work afterward
7.3. Interfaces require less code to need compiling
7.3.1. so utilize them
8. Getting Classes into Test Harness
8.1. Extract Interface
8.1.1. Mock out new interfaces
8.2. Hidden dependencies
8.2.1. Parameterized constructor
8.2.2. Supersede Instance Variable
8.2.2.1. Worst Case Scenario
8.2.2.2. Public Setter
8.3. Global Dependencies
8.3.1. Singletons
8.3.1.1. Relax it
8.3.1.1.1. Introduce static setter
8.4. Subclass
8.4.1. when difficult to construct, dependencies can be overwritten by a subclass
8.4.1.1. used as an interface to test desirable testable code
9. Get Method into Test Harness
9.1. Private method
9.1.1. test appropriate public methods
9.1.1.1. they will touch private methods, no need to test the private ones specifically
9.1.2. Make it public
9.1.2.1. if bad
9.1.2.1.1. fix class
9.1.3. Make it protected & subclass with a public method
9.1.3.1. java package level scope to circumvent the subclass
9.1.4. Reflection
9.1.4.1. Try to NEVER do this
9.1.4.1.1. sets bad presedence
9.1.4.1.2. can mask how bad a class is
10. Finding Bugs
10.1. Tests prevent future bugs
10.2. Once reducing the area a bug is in
10.2.1. write
10.2.1.1. Characterization Tests
10.2.1.1.1. Tests what the code does, not supposed to do
10.2.1.1.2. Ensures you are not breaking current working functionality
10.2.1.1.3. Steps
11. Adding Tests
11.1. Seam
11.1.1. Definition
11.1.1.1. Alter behavior in program without editing in that place
11.1.1.1.1. Test & Prod code IS THE SAME CODE
11.1.1.2. enabling point
11.1.1.2.1. spot to enable seam
11.1.2. Use indirect / hard seams to change legacy code very little so you can get tests in place
11.1.2.1. Then refactor
11.1.3. Types
11.1.3.1. Object Seam
11.1.3.1.1. Replace / Overwrite Object
11.1.3.2. Pre-Processing Seam
11.1.3.2.1. Compiler arguments to overwrite function definitions
11.1.3.3. Link Seam
11.1.3.3.1. Overwrite 'Linked'" / imported objects
11.1.3.3.2. Java