Akos Gyimesi wrote:

Now, later that day I decide that I pass the whole user object to the
check-pw function. Maybe I want to use the user ID as a salt, or maybe I
just want to leave the possibility for checking password expiration,
etc. So I modify the test and the implementation of check-pw so that the
first parameter is the user object, not the password hash.

Suddenly my co-worker comes to me saying "hey, I need you on a meeting
right now!" I close my laptop, and an hour later I think "where were
we?..." I run all the tests, and they all pass, so I commit.

What I'll often do in this case is start the change by marking every test that contains `check-pw` "pending" (using Midje's `future-fact`). Thereafter, running the test suite nags you about unfinished work.

The pending tests might include some set of mock tests, but it will also contain direct tests of `check-pw`. (I might also find that some uses of `check-pw` are in untested functions.)

Now to coding.

I would typically change the mock tests first. In that case, after you return from the interruption, the direct test(s) of `check-pw` will remind you that you're not finished.

You might instead work on the direct tests. In that case, the pending mock tests will remind you that you're not done.



Things get more complicated with more code. For example, we right now have nine (I think) Clojure services, plus a big library ("clojure commons") of shared code. When I have to change commons code, I'll often start by making a separate function (maybe called something obnoxious like check-pw-change-in-progress, maybe something different than `check-pw` but still sensible). I gradually migrate services over to the new version in the way described above. Eventually the original function can be deleted.

I'm sure this strategy is covered in Fowler's book on refactoring.

It's not always that simple. Monger 2.X was a big change from Monger 1.X (every function in the API grew an extra argument). Rather than make a minimal change to our getset.services.mongo, I did a function-generates-many-functions thing. That was more "big bang", and there was one problem that only got caught on the staging server by manual testing.



In the past, I would sometimes deliberately break the function being changed:

     (defn check-pw [])

... and run all the tests. That could tell me two things:

1. "You have an awful lot of "unit" tests that have nothing to do with passwords that nevertheless fail when `check-pw` [never mentioned in these tests] is changed." That's bad, if only because debugging is easier when only one test fails and it's a test that's "close to" the code that changed.

2. "None of your end-to-end tests test check the password form." As other people have noted, that means there's a class of bug that won't be caught by the test suite. On the other hand, end-to-end tests are harder to maintain than isolated unit tests. You have a tradeoff-type decision to make. In my case, I would almost always decide to forego the end-to-end test in this case. Instead, I'd make sure to exercise that form a little more thoroughly before I counted the story Done.

(More generally: the closer the code is to the "surface" of the app, the less need for end-to-end tests. It's the down deep code that makes me nervous. Way back in 1998, I wrote a paper explaining that thinking (in a different context): "When Should a Test Be Automated?" http://www.exampler.com/testing-com/writings/automate.pdf)

I seem to have drifted out of the habit of doing this. Not sure why. Maybe it's because doing in Clojure leads to multiple tests spewing huge swaths of stack trace garbage at me, and seeing that depresses me.


Hope this is of use.

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to