Using files as input

36 views
Skip to first unread message

Eric Kessler

unread,
Apr 9, 2020, 5:39:57 AM4/9/20
to rspec
I've looked around online a bit but cannot find any examples of (or evidence that it is even possible to) have RSpec run a set of specs listed in an arbitrary file as some other test frameworks can do. I don't really want to build a command line that is thousands of characters long in order to run many specific tests but I can easily stick the list of specs that I want to run in a file like this:

```
path/to/some_spec.rb[1:1:1]
path/to/some_spec.rb[1:2:1]
path/to/some_other_spec.rb[3:1]
...
etc.
```

Does RSpec have a mechanism that can handle that kind of input or am I limited to just specifying files and patterns on the command line?


Thanks,
Eric K

Jon Rowe

unread,
Apr 9, 2020, 5:44:17 AM4/9/20
to rs...@googlegroups.com
RSpec does not have this built in, but you don’t need it to be in order to achieve this, here is how to do that from a linux command line.

`rspec $(cat your_file.txt)`

Cheers
Jon Rowe
---------------------------

Eric Kessler

unread,
Apr 9, 2020, 6:02:48 AM4/9/20
to rspec


On Thursday, April 9, 2020 at 2:44:17 AM UTC-7, Jon Rowe wrote:
RSpec does not have this built in, but you don’t need it to be in order to achieve this, here is how to do that from a linux command line.

`rspec $(cat your_file.txt)`


That is a straightforward way of building a command line, yes, and I could certainly build such a command in pure Ruby (which would be my preference because I need cross-platform compatibility) before handing it off to whatever child process I need to execute it. However, I am cautious of that kind of approach because surely there is some practical limitation to how long a command can be. Yes, the internal test runner can easily iterate over an array that has a million or so entries but won't the Linux/Windows/OSX terminal that I have to feed the initial rspec command into complain about the command length at some point?

I'm looking for a general and reliable solution so that I don't have to worry about losing tests if the command gets cut short or have to come up with a new approach if the terminal errors out on the input or something. Currently, my alternative idea would be to build a string containing Ruby code that sucks in the file as an array and then hands that array to the RSpec test runner to execute. It isn't as elegant but I'm at least pretty certain that it will consistently work.


Eric K

Jon Rowe

unread,
Apr 9, 2020, 6:17:56 AM4/9/20
to rs...@googlegroups.com
Ah if you want to build something programmatic, you can use the configuration object.


You could use that to configure rspec to run a certain files contents e.g:

```
RSpec.configure do |config|
  filename = File.expand_path('../files.txt', __dir__)
  if File.exist?(filename)
    specs = File.read(filename).split("\n")
    puts "Loading #{specs.size} spec files from files.txt"
    config.files_to_run = specs
  end
end
```

Cheers
Jon Rowe
---------------------------

Philipp Pirozhkov

unread,
Apr 9, 2020, 8:06:43 AM4/9/20
to rs...@googlegroups.com
You can check command line length constraint with `xargs --show-limits`

For a deep dive, you can check https://github.com/ArturT/knapsack, a library that splits your specs across several workers, and see if there are some limitation workarounds there. I haven't seen much problems with using knapsack, so we can assume they do it in the correct way.

For the built-in mechanisms, you can check examples.txt and running `rspec --only-failures`.

- Phil

--
You received this message because you are subscribed to the Google Groups "rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rspec+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rspec/727fdb18-8631-45fe-98bd-94240984c951%40googlegroups.com.

Eric Kessler

unread,
Apr 12, 2020, 11:43:01 PM4/12/20
to rspec


On Thursday, April 9, 2020 at 3:17:56 AM UTC-7, Jon Rowe wrote:
Ah if you want to build something programmatic, you can use the configuration object.


You could use that to configure rspec to run a certain files contents e.g:

```
RSpec.configure do |config|
  filename = File.expand_path('../files.txt', __dir__)
  if File.exist?(filename)
    specs = File.read(filename).split("\n")
    puts "Loading #{specs.size} spec files from files.txt"
    config.files_to_run = specs
  end
end
```


This approach is promising and I'm giving it a try. However, `config.files_to_run` does not seem to accept the `file[x:x]` notation because it will try to `#load` the files and that notation is not a valid file path.

Thanks,
Eric K

Eric Kessler

unread,
Apr 13, 2020, 5:43:39 AM4/13/20
to rspec
So I dug into the RSpec code a little more and I did find a 'solution'. While `config.files_to_run = ['path/to/a_spec.rb[1:1:2:1:1:1]']` will run into loading issues, `config.instance_variable_set(:@files_or_directories_to_run ,  ['path/to/a_spec.rb[1:1:2:1:1:1]'])` will work. This seems to be because `@files_or_directories_to_run` is where the paths provided on the command line are stored when the command is parsed.

It's odd that, essentially, some kinds of configuration can only be provided via the command line, instead of any needed configuration being possible via the configuration object in code form.


Eric K

Jon Rowe

unread,
Apr 15, 2020, 4:59:44 AM4/15/20
to rs...@googlegroups.com
You can always run the runner programmatically instead, rather than shelling out. Someone is trying to do something similar to you here:


The issue is not that this cannot be provided, its more that your are trying to use the configuration to provide command line 

 configuration cannot be provided, its that its not cleared. 

The runner takes a list of files

Jon Rowe
---------------------------

Jon Rowe

unread,
Apr 15, 2020, 5:03:22 AM4/15/20
to rs...@googlegroups.com
Sorry disregard that last email, my mail client decided to send it prematurely. (I think I has muscle memory for new lines in Slack now :/)

You can always run the runner programmatically instead, rather than shelling out. Someone is trying to do something similar to you here:


Basically you can invoke the runner yourself with:

options = RSpec::Core::ConfigurationOptions.new(args)
RSpec::Core::Runner.new(options).run($stderr, $stdout)

Where args could be your file during into a list of strings.

Your issue is you are trying to pass runner options via config, which is not supported,(as we are primarily a command line tool) whilst their issue is just due to reusing some configuration but not all.

Cheers
Jon Rowe
---------------------------
Reply all
Reply to author
Forward
0 new messages