From: Shadowfirebird Date: 2008-08-02T19:36:25+09:00 Subject: Re: unit testing advice Thanks everyone. Now I need to go meditate to get my head around the idea of designing methods to be testable. It's quite a shift. Shadowfirebird. On Sat, Aug 2, 2008 at 2:24 AM, Phlip wrote: > Shadowfirebird wrote: > >> I've found this lovely bit of example code for mocha, though -- see >> below. If I understand you correctly, you seem to be saying that you >> *don't* test the output routine; you use a mock to fake it so that you >> can test the rest of the code? > > Consider a test T that calls A, which calls B. > > Sometimes, a B is cheap to assemble, so T can assemble B, activate A, and > test that A did its thing. T considers B's behavior just a side-effect. > > Most of the time, B should be real. And its state should be static (such as > a Rails "fixture", with static data.) B should not have runaway > dependencies. The test T should be easy to set-up. > > You should mock B if it's too expensive to set up. For example, if B reads > the system clock, and if T would prefer the date is 2008 July 31, the test T > should not wait an infinite amount of time, until the cosmos oscillates and > 2008 July 31 occurs again. Tests should run as fast as possible, to avoid > any hesitation running them. > > You should mock B, so it behaves as if the date is correct. Or you should > mock (in Ruby) Time.now, so all Ruby methods that use the date will read the > mocked date. > > Other examples of things too expensive to directly test: > > - live users > - random numbers > - hardware - networks, robots, tape drives, the clock, etc > - system errors > > If your B object is not on the list, you should not mock it. Unit tests work > best when they cross-test everything. The only thing better than a test that > fails because A broke is many tests that all accurately fail because B > broke. If your B is too expensive to assemble, you should refactor it, so it > bypasses the behavior that T and A did not care about. > >> class Enterprise >> def initialize(dilithium); @dilithium = dilithium; end >> >> def go(warp_factor); warp_factor.times { @dilithium.nuke(:anti_matter) >> }; end >> end > > Very nice. And note it obeys my list, by mocking both hardware and > space-time distortions. > > -- > Phlip > > -- Me, I imagine places that I have never seen / The colored lights in fountains, blue and green / And I imagine places that I will never go / Behind these clouds that hang here dark and low But it's there when I'm holding you / There when I'm sleeping too / There when there's nothing left of me / Hanging out behind the burned-out factories / Out of reach but leading me / Into the beautiful sea