- Administrivia - P1M1 due Friday - CS dept tutors available: http://www.cs.unm.edu/current_students/undergraduate_tutoring/ - Happy Labor day! (Monday). I will be out of town Fri/Sat/Sun, maybe/maybe not on Mon. ==================== - Testing principles/practices - P1M1 requires you to test your MHM implementation & demonstraste that you've tested it - What does that mean? How do you do it? - hint: you'll need to test _all_ of your programs in this class, so it's good to start learning now... - Principle #1: test early/divide and conquer - don't wait for the complete system to be coded before testing anything - test the smallest bits you possibly can - can actually start with MHM.Entry -- show that its (very, very simple) methods work right - for MHM: should begin testing when you have: get(), put(), size(), and isEmpty() - then do remove() - then do containsKey(), containsValue(), clear(), and putAll() - then equals() and hashCode() - then entrySet() - entrySet().size() - entrySet().iterator() - entrySet().contains() - finally keySet() and values() - note: this will require "stubbing out" methods so that you can get the compiler to accept your class - that's ok -- stub them out to start with (throw UnsupportedOperationException), and then fill them in as you can. - this is related to "unit testing" - unit testing == test the fundamental units of the program, rather than trying to test whole program at once - in OOP == test objects - I'm suggesting you actually go down below the level of the object... - So what does it mean to "test" a method? - demonstrate that it meets the spec - can be mathematically rigorous (under _any_ data input that obeys the input constraints, the outputs will be right, etc...) - that would be great, but it's a pain and is usually undoable - 2 schools of thought on testing - code coverage: make sure that you execute every line of code (e.g., both directions of each branch) - case coverage: make sure you test all expected uses of software - your goal: show that you handle the common cases and the edge cases - q: what's an "edge case"? - a: something that only happens at an extreme/boundary value - e.g., removing from an empty table, adding a huge number of records (show that resize works), adding/removing while iterating, putAll() on an empty/very large container. - also show that you can handle arbitrary objects, and that MHM can handle _mixed_ object types. - also think about "corner cases" - also, you need to show some results for _every_ method, in MHM as well as all of its sub-classes (!) - Principle #2: test often - run complete set of tests after every "substantial" update - e.g., after you get each new method working; every time you change anything about the underlying data structures; every time you add/delete/change a field or argument - that's a lot of testing! What's that about? - known as "regression testing" -- regress==opposite of progress. Has your code "regressed" because of something you did? Did something that worked before suddenly stop working? - So how do you make regression _practical_? - automation and repeatability are the keys