File fixture getting deleted after running RSpec tests - ruby

I have tests written in RSpec that have been passing up until an upgrade to Ruby 2.5.1.
The test in question has several let statements in a before(:each) block. The file that keeps getting deleted is in there like so:
let(:fake_s3_file) { File.open(File.join(File.dirname(__FILE__), '../fixtures/Alexa.pdf')) }
Later in before(:each) stanza, I have this:
allow(s3_client).to receive(:get_object).and_return(fake_s3_file)
allow(Tempfile).to receive(:new).and_return(fake_s3_file)
It appears that in Ruby 2.5.1, my source files are getting deleted, either because of the File.open or the Tempfile reference. Has anyone run into this, and what is a good way around this? I haven't found any docs that say any changes have happened to Tempfile or to File.open. Should I copy my fixture file into a /tmp directory before every spec run? It seems wrong to do that, and slow.

Related

Testing a Jekyll site with rspec and capybara, getting a bizarre race-case on rspec start

So check this out: it appears as though, upon running bundle exec rspec, there's a race between jekyll serve and puma/rspec's boot up. Sometimes I run the command, and my tests run fine. Other times, I get the error for each of my spec files: cannot load such file -- /path/to/project/sitename_jekyll/_layouts/spec/form_spec.rb which is interesting cause that's not where my spec files are located. They're in /path/to/project/sitename_jekyll/spec/form_spec.rb.
What's crazy is that I can literally just re-run the command over and over and over again and sometimes it'll go through and run the spec tests in the correct location, and sometimes it'll look for them in _layouts and error out. It probably runs correctly maybe once out of ever three or five attempts. All the other times I get the following errors:
Here's what my spec_helper.rb looks like: https://gist.github.com/johnhutch/2cddfafcde0485ff021501d5696c0c2d
And here's an example test file:
https://gist.github.com/johnhutch/a35d15c170f5fd9ca07998bf035d111d
My .rspec only contains two lines:
--color
--require spec_helper
And here's the output, both successful and unsuccesful, back to back:
https://gist.github.com/johnhutch/7927d609170ef5c70a595735502b128d
HEEELLLLLP!
This sounds like jekyll is changing the current directory while building the site, which since it is being run in a thread also affects the tests RSpec is trying to run (See https://bugs.ruby-lang.org/issues/9785 for why Dir.chdir is not threadsafe) - leading to attempts to load things from incorrect locations.
A potential solution to this would be to wait for the Jekyll site to be built before actually running your tests. A comment in your spec_helper seems to state that someone thought passing force_build: true would do this but from a quick perusal of the jekyll-rack code I don't think that's true and you actually need to wait for compiling? to return false (v 0.5) (complete? to return true in the current master branch) to ensure building has finished (as well as passing force_build). This could either be done in a loop sleeping and checking (simpler)
sleep 0.1 while <jekyll app>.compiling?
or (if using the master branch) via the mutex/conditional Rack::Jekyll exposes like in its test suite - https://github.com/adaoraul/rack-jekyll/blob/master/test/helper.rb#L49
Note: Also check my comment about your tests that aren't actually testing anything.
As per Thomas Walpole's super helpful responses this ended up working:
sleep 0.1 while Capybara.app.compiling?
inserted right after:
51 Capybara.app = Rack::Jekyll.new(force_build: true)
in my spec_helper.rb
Thanks again, Thomas!

Stop Loading spec_helper from spec directory when running another set of tests

I have two spec folders. The first one is /spec and it what you typically would see. I have another called /live_integration_tests. When I run rspec -I live_integration_tests ./live_integration_tests I'm actually pulling in the spec/spec_helper.rb file as well. Is there a way to get rspec to ignore the spec_helper file in the spec_helper folder.
I've also tried rspec -O live_integration_tests/spec_helper.rb ./live_integration_tests
but that didn't do it either. Everything else in the help didn't look very promising.
I found a fix for this.
rspec --default-path ./live_integration_tests runs only the rspec spec_helper in the ./live_integration_test folder and not the default one in ./spec.

Why RSpec runs specs twice when running from within ruby and spec file is reloaded?

I'm trying to use RSpec from within existing ruby runtime and run specs every time when file changes. This is because of JRuby and JVM startup time. To eliminate this on every run I'd like to start ruby once, then only reload changed files and run specs. I was using guard (with diffrent extensions) and watchr but all seem to suffer from an issue described below.
I nailed the issue down to RSpec itself. The problem is, when running RSpec via RSpec::Core::Runner.run several times it works fine until spec file is reloaded using load. Then RSpecs starts running specs twice.
I've created sample project showing this issue live: https://github.com/mostr/rspec_double_run_issue
Below is sample output:
ruby run_spec_in_loop.rb
Running spec from within ruby runtime
.
Finished in 0.00047 seconds
1 example, 0 failures
loading spec file via 'load' as if it was changed and we wanted changes to be picked up
Running spec from within ruby runtime
..
Finished in 0.001 seconds
2 examples, 0 failures
Is there any way to tell RSpec to clear its context between subsequent runs when run from within existing ruby runtime? I've also raised this as an issue #826 for RSpec Core project.
Summarizing the answer here in order to remove this question from the "Unanswered" filter...
Per RJHunter's observation, the explanation has been documented on the GitHub RSpec Core project here:
https://github.com/rspec/rspec-core/issues/826#issuecomment-15089030
For posterity (in case the above link dies), here are the details:
The RSpec runner is already calling load internally, your second load is what's causing the double run issue.
I quickly knocked up a script based off your example which reruns a single spec file, changes the specs to something else, then reruns them, work's correctly without the second load
See: https://gist.github.com/JonRowe/5192007
The aforementioned Gist contains:
require 'rspec'
spec_file = 'spec/sample_spec.rb'
File.open(spec_file, 'w') { |file| file.write 'describe { specify { expect(true).to eq false } }' }
1.upto(5) do |i|
puts "Running spec from within ruby runtime"
::RSpec::Core::Runner.run([spec_file], STDERR, STDOUT)
#rewriting the spec file
File.open(spec_file, 'w') { |file| file.write "describe { specify { expect(#{i}).to eq false } }" }
end

RSpec Autotest loops with failures, doesn't work when exceptions are added

I've been playing around with autotest trying to make it work all day.. but am having some problems...
I've been following https://github.com/rspec/rspec/wiki/autotest, I'm running with:
Ruby 1.9.3-p194
rspec 2.10.0
ZenTest 4.8.1
I also created a .rspec file.
So with this setup, I run autotest, and it works - my test runs, it passes, hooray!. When I stick a failure into my test e.g. false.should == true, then the test starts looping, over and over again.
what happens is that it's an integration test, and I'm writing to an sqlite db. If I run find . -mmin -1 then I'm able to see that my db folder has changed - so I figured this is the problem.
So I edit .autotest and add the following:
Autotest.add_hook :initialize do |autotest|
%w{db}.each { |exception| autotest.add_exception(exception) }
false
end
But now when I run autotest, it just says the following:
loading autotest/rspec2
and that's it, it won't do anything anymore. Previously the output was:
loading autotest/rspec2
/home/me/.rbenv/versions/1.9.3-p194/bin/ruby -rrubygems -S '/home/me/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/rspec-core-2.10.1/exe/rspec' ``--tty '/home/me/Workspace/myproject/spec/integration/db/lead_spec.rb'
and then it'd run my test and show the result...
Anyone know what could be going on? it's very frustrating, and I feel like I've come to a road block....
Thanks for your help!
Autotest checks if defined exceptions match any part of the filename. Your spec has db in it's path so it is ignored by autotest.
If you want to ignore db folder, then do the following:
Autotest.add_hook :initialize do |a|
a.add_exception %r{^\./db}
end

Ruby separate large source files into multiple files

I am writing a Ruby script which was supposed to be a small thing but has grown quite large, way to large to have everything crammed into one source file. So I am trying to separate the project into different files. I have four classes and I want to put each in its own separate source file.
What I did:
I moved all of the classes into their own files so now I have this
proj/GoogleChart.rb
proj/BarChart.rb
proj/PieChart.rb
proj/GroupedBarChart.rb
Now that they are in other files I am getting uninitialized constant GoogleChart (NameError) in all of my subclasses on the line where I inherit from GoogleChart, i.e.
require 'GoogleChart'
BarChart < GoogleChart
Can anyone tell me what is wrong?
Thanks
EDIT
Using ruby version 1.8.4
Also I have tried using the absolute path:
require 'C:/Documents and Settings/proj/GoogleChart.rb' and this is still producing a NameError
In Ruby 1.8.x, the . is part of your load path. So you should at least try to debug that by including something like:
puts $:
require 'GoogleChart'
class BarChart < GoogleChart
end
and load that in an IRB session:
Open the session in your directory proj.
Enter there require 'BarChart'
Look at the result.
For me it is:
c:\apps\ruby\test\proj>irb
irb(main):001:0> require 'BarChart'
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8/i386-msvcrt
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8/i386-msvcrt
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8/i386-mingw32
.
=> true
So the require is successful for me, and the . is part of the path (as it should). As you can see, I am working with Ruby 1.8.7, I don't know if anything has changed since 1.8.4 that is relevant here.
So please describe exactly how you run your file:
Have you opened a shell to run the file?
What is the current working directory of that shell?
Do you run by double-clicking it?
It only works when you are in your proj directory and run there (with ruby in your shell path) ruby BarChart.rb.

Resources