0

I'm currently issuing a problem with running tests with rspec. All the test files (*_spec.rb) may run successfully. In same rare cases an error -- Errno::EACCES may appear and one of the tests may fail. E.g:
All the test in the file *_spec.rb run:

  1. Successfully.
  2. Successfully.
  3. One the test had failed.
  4. Successfully.
  5. One the test had failed (not the same as in #3).
  6. etc.

The exception raises from the lines like:

  1. FileUtils.mv
  2. FileUtils.mkdir_p
  3. FileUtils.rm_r

All of those list work with files or directories and are used many times in tests. I.e.:
create folder(with subfolders, with files, etc.), rename folder, test something, delete.. and so on.

It looks like the problem is hidden somewhere in "timing"(if something is not done yet and another action tries to access that something). That mind comes from:

begin
  FileUtils.mv(a, b) # if an `Errno:EACCESS` was raised here
rescue               #
  FileUtils.mv(a, b) # it wouldn't be raised now
end

The question is:
How can it be fixed? (i mean Errno:EACCESS which is reproduced rarely and some tests)


  • Adding sleep after every operation with files is not acceptable nevertheless it will help.
  • ruby's methods (FileUtils.(mv|rm_r|mkdir_p)) may be modified to retry once on Errno::EACCES but is this the best solution?

P.S.
Sorry for my English and feel free to ask any question as i've tried to explain as brief as i could. Thanks in advanced, at least for you've read this to the end;

ted
  • 5,219
  • 7
  • 36
  • 63

1 Answers1

0

Look for the root cause, don't succumb to workarounds you mentioned.

First make sure you're using before and after for setting up and tearing down file fixtures. If you code your setup and teardown procedures in the spec itself you run a risk of it not running when the test fails.

Second, make sure your setup & teardown procedures create different files and directories for each test. If all you're doing is reading it's ok to use shared fixtures, but for all other things (moving, creation, appending, deletion) use a fresh file/directory. The best thing to do is to use freshly generated temporary files and directories. It will make your tests independent, even allowing to run them in parallel.

Third, check what other processes may use files created/used by your tests. I don't know your setup, and it all depends on that, but possible things are web servers, browsers (e.g. via selenium), mail servers, etc. Simply check what other processes are you running as a part of your build.

Michał Kwiatkowski
  • 9,196
  • 2
  • 25
  • 20
  • `create different files and directories for each test` -- you mean if i have 100 tests with [(before test)mkdir_p(a), testing, (after test)rm_r(a)] `a` should not be a constant like: `a = 'temp/something'`? – ted Aug 29 '12 at 11:11
  • Before every test a new folder is created and after it -- deleted. None of the processes are using tests' "output data". – ted Aug 29 '12 at 11:18
  • Yes, it's best to use random temporary names, see http://apidock.com/ruby/Tempfile This way you can run your tests in parallel and there's a lesser chance of one test affecting another. – Michał Kwiatkowski Aug 29 '12 at 14:50
  • If you're getting `Errno:EACCESS` exception then note for what file it was raised. Trace the source of the problem and try to debug it. Without more details (like the responsible piece of the code) I can't help you any further. – Michał Kwiatkowski Aug 29 '12 at 14:52
  • OK, you got the place in code that raises the exception, but you also need the values, in this case "src" and "dest". Check what are they when the exception is raised. Knowing which file causes the exception may give you a hint as to why it is raised. If not, well, you have to read your test and application code and look for methods/processes that share this file or modify permissions. – Michał Kwiatkowski Aug 30 '12 at 09:26
  • Actually, it doesn't matter what `src` and `dest` are for exception to be raised. `dest` is always like `"temp\b"` (path to folder) which doesn't exist yet and `src` is `"temp\a"` (path to folder) which exists. The same test may run successfully 10 times and fail on 11th with nothing changed at all. – ted Aug 30 '12 at 09:37