@@ -218,16 +218,76 @@ to delete the original *clean_party* function in _lib/parser.py_. Ideally, we'll
218
218
219
219
##### Exercises
220
220
221
+ ### Add vote
222
+
223
+ Each candidate has a single name and party (well, usually), and numerous county-level results.
224
+ As part of our summary report, county-level results need to be rolled up into a racewide total for each candidate.
225
+ At a high level, it seems natural for each candidate to track his or her own vote totals.
226
+
227
+ Below are a few other basic assumptions, or requirements, that will help us flesh out
228
+ vote-handling code on the Candidate class:
229
+
230
+ * A candidate should start with zero votes
231
+ * Adding a vote should increment the vote count
232
+ * County-level results should be accessible
233
+
234
+ With this basic list of requirements in hand, we're ready to start coding. For each requirement, we'll start by
235
+ writing a (failing) test that captures this assumnption; then we'll write code to make the test pass. The goal
236
+ is to capture our assumptions in the form of tests, and then write code required to meet those assumnptions.
237
+
238
+ 1 . Add test for zero vote count as initial Candidate state ([ elex4.3.0] [ ] )
239
+
240
+ > Note: We created a new * TestCandidateVotes* class with a * setUp* method that lets us
241
+ > re-use the same candidate instance across all test methods. This
242
+ > makes our tests less brittle -- e.g., if we add a parameter to the
243
+ > Candidate class, we only have to update the candidate instance in
244
+ > one the * setUp* method, rather than in every test method (as
245
+ > we will have to in the * TestCandidate* class)
246
+
247
+ 1 . Run test; see it fail
248
+ 1 . Update Candidate to have initial vote count of zero ([ elex4.3.1] [ ] )
249
+ 1 . Run test; see it pass
250
+ 1 . Add test for * Candidate.add_votes* method ([ elex4.3.2] [ ] )
251
+ 1 . Run test; see it fail
252
+ 1 . Create the * Candidate.add_votes* method ([ elex4.3.3] [ ] )
253
+ 1 . Run test; see it pass
254
+ 1 . Create test for county_results attribute ([ elex4.3.4] [ ] )
255
+ 1 . Run test; see it fail
256
+ 1 . Update * Candidate.add_votes* method to store county-level results ([ elex4.3.5] [ ] )
257
+ 1 . Run test; see it pass
258
+
259
+ [ elex4.3.0 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.0/elex4/tests/test_models.py " test_models.py "
260
+ [ elex4.3.1 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.1/elex4/lib/models.py " lib/models.py "
261
+ [ elex4.3.2 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.2/elex4/tests/test_models.py " test_models.py "
262
+ [ elex4.3.3 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.3/elex4/lib/models.py " lib/models.py "
263
+ [ elex4.3.4 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.4/elex4/tests/test_models.py " test_models.py "
264
+ [ elex4.3.5 ] : https://github.com/PythonJournos/refactoring101/blob/elex4.3.5/elex4/lib/models.py " lib/models.py "
265
+
266
+ #### Questions
267
+
268
+ * What does the TestCase * setUp* method do?
269
+ * The test methods * test_vote_count_update* and * test_county_results_access*
270
+ each add 20 votes to the candidate instance created in * setUp* . Why
271
+ are candidate votes equal to 20 in both tests, instead of
272
+ adding up to 40 in one of them (which would cause a test failure)?
273
+ * In what order are test methods run?
274
+ * What other unittest.TestCase methods are available?
275
+
276
+ #### Exercises
277
+
278
+ * Read the [ unittest docs] [ ] page.
279
+ * The * Candidate.add_votes* method has a potential bug: It can't handle votes that are strings instead of proper integers.
280
+ This bug might crop up if our parser fails to convert strings to integers. Write a test to capture the bug, then update
281
+ the method to handle such "dirty data" gracefully.
282
+
283
+ [ unittest docs ] : http://docs.python.org/2/library/unittest.html
221
284
222
285
## TODO
223
286
224
- * Candidate.votes
225
287
* Race.office and district
226
288
* Race.add_result (gets or creates candidate instance)
227
289
* Candidate.winner, margin, vote_pct (since these require all Candidates to be available via parent Race class)
228
290
* Write high-level tests for summarize output
229
291
* Update Parser to return Candidate and Race classes
230
292
* Update summary script to use Cand/Race objects returned by Parser class
231
293
232
-
233
-
0 commit comments