简体   繁体   中英

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM