James Byrne
2009-Feb-09 15:12 UTC
[rspec-users] RSpec Testing ActiveRecord config dependency.
I have the following library code: def normal_time_now return DateTime.now.utc if default_timezone == :utc return DateTime.now end This is dependent upon a setting in config/environment.rb # Make Active Record use UTC-base instead of local time config.active_record.default_timezone = :utc I want to test that I get the expected results with the config set to utc and otherwise. The library code is used to automatically set a model attribute on create. My existing specification looks somewhat like this: describe "Builds a Model with custom magic columns" do before(:all) do build_model :magiks do string :description # these are Rails'' own magic columns ... # these are our custom magic columns ... end @my_mage = Magik.new @my_mage.save! end it "should set each custom magic column present" do (Magik.column_names & ActiveRecord::Base::HLL_AUDIT_COLUMNS).each do |magic_column| @my_mage.read_attribute(magic_column).should_not be_nil end end I can simply create duplicate separate specification file and set the configuration value appropriately in each. Something along the lines of: describe "Builds a Model with custom magic columns" do before(:all) do config.active_record.default_timezone = nil or config.active_record.default_timezone = :utc But this strikes me as inappropriate. I believe that this test belongs inside the basic specification file but I cannot conceive of how to do this. Basically, I require some form of variable setup routine. Does anyone have any suggestions on how to handle this case? Regards, -- Posted via http://www.ruby-forum.com/.
David Chelimsky
2009-Feb-09 18:11 UTC
[rspec-users] RSpec Testing ActiveRecord config dependency.
On Mon, Feb 9, 2009 at 9:12 AM, James Byrne <lists at ruby-forum.com> wrote:> I have the following library code: > > def normal_time_now > return DateTime.now.utc if default_timezone == :utc > return DateTime.now > end > > This is dependent upon a setting in config/environment.rb > > # Make Active Record use UTC-base instead of local time > config.active_record.default_timezone = :utc > > I want to test that I get the expected results with the config set to > utc and otherwise. The library code is used to automatically set a > model attribute on create. My existing specification looks somewhat > like this: > > describe "Builds a Model with custom magic columns" do > before(:all) do > build_model :magiks do > string :description > # these are Rails'' own magic columns > ... > # these are our custom magic columns > ... > end > @my_mage = Magik.new > @my_mage.save! > end > > it "should set each custom magic column present" do > (Magik.column_names & ActiveRecord::Base::HLL_AUDIT_COLUMNS).each do > |magic_column| > @my_mage.read_attribute(magic_column).should_not be_nil > end > end > > I can simply create duplicate separate specification file and set the > configuration value appropriately in each. Something along the lines of: > > describe "Builds a Model with custom magic columns" do > before(:all) do > config.active_record.default_timezone = nil > or > config.active_record.default_timezone = :utc > > But this strikes me as inappropriate. I believe that this test belongs > inside the basic specification file but I cannot conceive of how to do > this. Basically, I require some form of variable setup routine. Does > anyone have any suggestions on how to handle this case?I''d keep it isolated. You know that config.active_record.default_timezone = :utc works, right? So you don''t need to specify that. You''re specifying that when default_timezone == :utc, it behaves one way, but otherwise it behaves differently. So: magik = Magik.create def magic.default_timezone; :utc; end .... OR magik = Magik.create magik.stub!(:default_timezone).and_return(:utc) Now this violates a principle that you shouldn''t stub things on the object you''re spec''ing, but the alternative is to play with global values, which violates other principles. This is the simplest way IMO. But if you''re concerned about internals of AR changing, you could do this: describe Thing do before(:each) do @original_default_timezone = Thing.default_timezone end it "does something" do Thing.default_timezone = :abc thing = Thing.new thing.default_timezone.should == :abc end before(:each) do Thing.default_timezone = @original_default_timezone end end That will restore things after each example. HTH, David> > Regards, > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
James Byrne
2009-Feb-09 19:22 UTC
[rspec-users] RSpec Testing ActiveRecord config dependency.
David Chelimsky wrote:> Now this violates a principle that you shouldn''t stub things on the > object you''re spec''ing, but the alternative is to play with global > values, which violates other principles. This is the simplest way IMO. > But if you''re concerned about internals of AR changing, you could do > this:Since my library extends ActiveRecord::Base and its magic datetime columns I think that I should test that my extension does not change the anticipated behaviour of AR itself. However, default_timezone cannot be set on an instance of AR:Base insofar as I can tell. Further, setting the default_timezone on AR:Base itself does not appear to have any effect: [ "local", "utc" ].each do |tz| ActiveRecord::Base.default_timezone = tz @my_mage = Magik.new @my_mage.description = tz @my_mage.my_time_local = DateTime.now @my_mage.my_time_utc = DateTime.now.utc @my_mage.save! puts @my_mage.description end ... it "should set the UTC time (for _at/_on) correctly" do my_magic = Magik.find_by_description!("local") puts " " puts my_magic.description puts "Local: #{my_magic.my_time_local} = #{my_magic.my_time_local.to_f}" puts " now: #{Time.now} = #{Time.now.to_f}" puts " UTC: #{my_magic.my_time_utc} = #{my_magic.my_time_utc.to_f}" puts " now: #{Time.now.utc} = #{Time.now.utc.to_f}" my_magic = Magik.find_by_description!("utc") puts " " puts my_magic.description puts "Local: #{my_magic.my_time_local} = #{my_magic.my_time_local.to_f}" puts " now: #{Time.now} = #{Time.now.to_f}" puts " UTC: #{my_magic.my_time_utc} = #{my_magic.my_time_utc.to_f}" puts " now: #{Time.now.utc} = #{Time.now.utc.to_f}" Produces this: ..... local Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77585 UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.77609 utc Local: Mon Feb 09 14:20:06 UTC 2009 = 1234189206.0 now: Mon Feb 09 14:20:06 -0500 2009 = 1234207206.77807 UTC: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.0 now: Mon Feb 09 19:20:06 UTC 2009 = 1234207206.7783 . Finished in 0.429892 seconds It seems that I am not overriding the AR:BASE.default_timezone setting since, as far as I can tell, the values stored are the same whatever value I set the default_tz to. Does anyone have a technique to accomplish this? -- Posted via http://www.ruby-forum.com/.
James Byrne
2009-Feb-09 22:23 UTC
[rspec-users] RSpec Testing ActiveRecord config dependency.
James Byrne wrote:> It seems that I am not overriding the AR:BASE.default_timezone setting > since, as far as I can tell, the values stored are the same whatever > value I set the default_tz to. >Well, after a very frustrating afternoon I have finally uncovered what is going on. The problem I had is that I did not consider that AR::Base.default_timezone is used both in and out. The display of datetime values retrieved via AR is adjusted according to the default_timezone setting at the time of retrieval and is not based on any TZ value stored in the database. In my test setup I created rows with the tz value set to :utc and then :local. However, when I ran the tests then I did not bother to reset the tz appropriately for each test. Thus the display of the data was adjusted by AR and confused the hell out of me. -- Posted via http://www.ruby-forum.com/.