On 7/29/07, Russell Tracey <[EMAIL PROTECTED]> wrote: > On 29/07/07, David Chelimsky <[EMAIL PROTECTED]> wrote: > > On 7/29/07, Russell Tracey <[EMAIL PROTECTED]> wrote: > > > I'm currently taking a Rails project management app I built when > > > learning Rails and adding specs to it. During the course of building > > > the app the requirement that project should be archiveable was added. > > > So a project is in one of two states active or archived. > > > > > > This led to the creation of the following methods: > > > > > > Project.active_projects > > > Project.archived_projects > > > > > > @project.active? > > > @project.archived? > > > @project.archive! > > > @project.unarchive! > > > > > > The current implementation of this is using a separate table of > > > "visibilities" as follows: > > > > > > # Implementation 1 (Current) > > > > > > Tables: > > > > > > Project > > > id name visibility_status_id > > > 1 ActiveProject 1 > > > 1 ArchivedProject 2 > > > > > > VisibilityStatuses > > > id name > > > 1 Live > > > 2 Archived > > > > > > But the same behavior could be implemented using a datetime column as > > > follows: > > > > > > # Implementation 2 > > > > > > Tables: > > > > > > Project > > > id name archived_at > > > 1 ActiveProject null > > > 1 ArchivedProject 2007-07-29:18:57 > > > > > > Or in fact numerous other ways e.g. > > > > > > # Implementation 3 > > > > > > Army of cows: > > > > > > Each cow represents a project, the cows wear one of two hats > > > to indicate the active/archived status of the project they represent. > > > > > > ...and so on. > > > > > > It's my understanding that model specs (and specs in general) should > > > be shielded from the implementation details, so how do i check that > > > Project.active_projects only returns active projects without looking > > > at assuming something about the implementation? My initial thought is > > > to check each of them using one of the other exposed methods above, in > > > this case... > > > > > > Project.active_projects.all? {|p| p.active? } > > > > > > but then i can't work out how to spec all the other methods without > > > going round in circles so that each spec would end up assuming that > > > the other methods work (in this case that p.active? is working) or > > > worse resorting to peeking at implementation details. > > > > Keep in mind that back-filling examples to existing code is a very > > different process from writing the examples first, which is the > > situation for which RSpec is intended. In that case, you might start > > with one example like this: > > > > describe Project do > > it " should not be active by default" do > > project = Project.create > > project.should_not be_active > > end > > end > > > > Then the next example might be that when you activate it should be active: > > > > describe Project do > > it " should not be active by default" { ... } > > > > it "should be active after you activate it" do > > project = Project.create > > project.activate! > > project.should be_active > > end > > > > it "should show up in the list of active projects when activated" do > > project = Project.create > > project.activate! > > Project.active_projects.should include(project) > > end > > end > > > > etc. > > > > In this second pair of examples, we never "test" the activate! method > > in terms of looking at its internal effects (i.e. that it changes > > something in the database), but rather through the difference in the > > way the object behaves after having called the activate! method. > > > > Make sense? > > > > David > > _______________________________________________ > > rspec-users mailing list > > rspec-users@rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > > Yes this is making more sense now, the only remaining thing i am > wondering is, given the above examples, would specing that > active?/archived? be possible without resorting to implementation > details that Kyle wrote about. If i'm reading them correctly the > examples above spec out the behavior of activate!, active_projects and > the default state of a project after creation, but don't define the > behavior of active? > > In this app the projects are actually "active" by default before being > archived at some point later. So they are only ever in one of two > states, active or archived. > > I'm thinking something like this > > describe Project do > ... > it " Not sure what this would be called?" do > project = Project.create > project.should be_active > > project.archive! > > project.should_not be_active > end > end
Changing state between expectations in one example is a TDD no-no. The reason is that if "project.should be_active" fails, you might do something to fix it and then find that "project.should_not be_active" fails. If you have them in separate examples then the fact that only one fails and not the other gives you better feedback: describe Project do it "should be active when first created" do project = Project.create project.should be_active end it "should not be active after it is archived" do project = Project.create project.archive! project.should_not be_active end end > _______________________________________________ > rspec-users mailing list > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users