RSpec seems to be popular in the rails world, so I used rspec to write my tests. This exercise provided me with examples of the good, the bad, and the ugly with unit tests. The good was straightforward. I don't have an application yet, just this simple library and unit tests provided an easy way to test it. Even better, at one point I changed an implementation detail that required some rewriting of the property model, and by rerunning the tests, I had confidence that I didn't break anything.
The ugly? This is definitely a good example of ugly. I have the unit testing code at the bottom of this post. I found I had a lot of duplication, so I created "shared_examples_for" to reduce redundancy. However, the resulting test code is still really long and while the shared examples helps with sharing tests, I am not sure they help with readability. Now, as Trevor commented, its possible (ok, likely) that the unit tests are ugly because they weren't written well. I will admit to being a newbie at RSpec. I am sure that they could be written better, but I am not convinced they wouldn't still be somewhat ugly.
The bad? Well, there isn't too much bad, yet. It did take time to create the tests, but I had to validate my code somehow. And it is possibly (likely?) that my tests aren't as thorough as they should be, so maybe I have some false confidence in the correctness of my code. But all in all, despite what I said last paragraph, this wasn't that good of an example of the bad. At least not yet. The bad will come when I spend time trying to clean up these tests, rather than using that time to write new code.
And without further ado, here are these unit tests.
require 'spec_helper' describe Thing do let(:foo) {5} let(:bar) {"hello"} shared_examples_for "simple properties" do describe "keys" do it {thing.keys.size.should == 2} end describe "foo" do it {thing['foo'].should == foo} it {thing.foo.should == foo} end describe "bar" do it {thing['bar'].should == bar} it {thing.bar.should == bar} end describe "baz" do it {thing['baz'].should be_nil} it {thing.baz.should be_nil} end describe "to_hash" do it {thing.to_hash.should_not be_nil} it {thing.to_hash.size.should == 2} it {thing.to_hash['foo'].should == foo} it {thing.to_hash['bar'].should == bar} end end shared_examples_for "nested properties" do describe "keys" do it {thing.keys.size.should == 4} it {thing.self_keys.size.should == 2} it {thing.self_keys.include?('b2').should be_true} it {thing.self_keys.include?('bye').should be_true} it {thing.self_keys.include?('bar').should be_false} end describe "foo" do it {thing['foo'].should == 5} it {thing.foo.should == 5} end describe "bar" do it {thing['bar'].should == "hello"} it {thing.bar.should == "hello"} end describe "b2" do it {thing['b2'].should == 15} it {thing.b2.should == 15} end describe "bye" do it {thing['bye'].should == "bye"} it {thing.bye.should == "bye"} end describe "baz" do it {thing['baz'].should be_nil} it {thing.baz.should be_nil} end describe "to_hash" do it {thing.to_hash.should_not be_nil} it {thing.to_hash.size.should == 4} it {thing.to_hash['foo'].should == 5} it {thing.to_hash['bar'].should == "hello"} it {thing.to_hash['b2'].should == 15} it {thing.to_hash['bye'].should == "bye"} end end describe "no inheritance" do let(:thing) {Thing.new} subject {thing} describe "new object" do describe "keys" do it {thing.keys.should_not be_nil} it {thing.keys.should be_empty} end describe "properties" do it {thing['foo'].should be_nil} it {thing.foo.should be_nil} end describe "to_hash" do it {thing.to_hash.should_not be_nil} it {thing.to_hash.size.should == 0} end end describe "adding properties to object" do before(:each) do thing['foo'] = 5 thing['bar'] = "hello" end it_should_behave_like "simple properties" it {thing.self_keys.size.should == 2} it {thing.self_keys.include?('foo').should be_true} it {thing.self_keys.include?('bar').should be_true} it {thing.self_keys.include?('baz').should be_false} end describe "adding fields to object" do before(:each) do thing.foo = 5 thing.bar = "hello" end it_should_behave_like "simple properties" it {thing.self_keys.size.should == 2} it {thing.self_keys.include?('foo').should be_true} it {thing.self_keys.include?('bar').should be_true} it {thing.self_keys.include?('baz').should be_false} end end describe "inheritance" do let(:thing) do base = Thing.new base.foo = 5 base['bar'] = 'hello' foo = Thing.new foo.prototype = base foo end subject {thing} describe "new object" do it_should_behave_like "simple properties" it {thing.self_keys.include?('bar').should be_false} it {thing.self_keys.include?('baz').should be_false} end describe "adding properties to object" do before(:each) do thing['b2'] = 15 thing['bye'] = "bye" end it_should_behave_like "nested properties" end describe "adding fields to object" do before(:each) do thing.b2 = 15 thing.bye = "bye" end it_should_behave_like "nested properties" end describe "adding redundant fields to object" do let(:foo) {15} let(:bar) {"bar2"} before(:each) do thing.foo = foo thing.bar = bar end it_should_behave_like "simple properties" it {thing.self_keys.size.should == 2} it {thing.self_keys.include?('foo').should be_true} it {thing.self_keys.include?('bar').should be_true} it {thing.self_keys.include?('baz').should be_false} end end end
And here is the output of running the above tests:
$ rspec spec/models/thing_spec.rb Thing no inheritance new object keys should not be nil should be empty properties should be nil should be nil to_hash should not be nil should == 0 adding properties to object should == 2 should be true should be true should be false it should behave like simple properties keys should == 2 foo should == 5 should == 5 bar should == "hello" should == "hello" baz should be nil should be nil to_hash should not be nil should == 2 should == 5 should == "hello" adding fields to object should == 2 should be true should be true should be false it should behave like simple properties keys should == 2 foo should == 5 should == 5 bar should == "hello" should == "hello" baz should be nil should be nil to_hash should not be nil should == 2 should == 5 should == "hello" inheritance new object should be false should be false it should behave like simple properties keys should == 2 foo should == 5 should == 5 bar should == "hello" should == "hello" baz should be nil should be nil to_hash should not be nil should == 2 should == 5 should == "hello" adding properties to object it should behave like nested properties keys should == 4 should == 2 should be true should be true should be false foo should == 5 should == 5 bar should == "hello" should == "hello" b2 should == 15 should == 15 bye should == "bye" should == "bye" baz should be nil should be nil to_hash should not be nil should == 4 should == 5 should == "hello" should == 15 should == "bye" adding fields to object it should behave like nested properties keys should == 4 should == 2 should be true should be true should be false foo should == 5 should == 5 bar should == "hello" should == "hello" b2 should == 15 should == 15 bye should == "bye" should == "bye" baz should be nil should be nil to_hash should not be nil should == 4 should == 5 should == "hello" should == 15 should == "bye" adding redundant fields to object should == 2 should be true should be true should be false it should behave like simple properties keys should == 2 foo should == 15 should == 15 bar should == "bar2" should == "bar2" baz should be nil should be nil to_hash should not be nil should == 2 should == 15 should == "bar2" Finished in 0.06217 seconds 106 examples, 0 failures
1 comment:
c++ graphic coding examples
logical discription of logial errors in graphics
Post a Comment