Combining RSpec filters? - ruby

I've been looking through the docs, but descriptions of how multiple filters work seem to be a bit lacking. Does anyone have a good explanation or source of a good explanation for the behaviour of multiple filters? Does the order they are listed matter? Here's an example of code that might have behaviour other than what one could expect...
Rspec.configure do |c|
this_version = get_version_number.to_sym
c.filter_run :focus=> true
c.filter_run_excluding :limit_to=>true, this_version => false
c.filter_run :new_stuff=>true
c.run_all_when_everything_filtered
end
it "is focused, but not new", :focus
it "is is new", :new_stuff
it "is new and focused", :new_stuff, :focus
it "is focused and new, but limited to a different version", :focus, :limit_to, :correct_version
Experimenting with this, it also seems like multiple arguments on the "filter_run_excluding" line simple act is if you wrote the line multiple times. Is there a way to get it to actually combine the filter checks so that it excludes (or runs, I suppose) only examples that have both the tags listed?

Run multiple filters from the command line with this:
rspec spec --tag my_tag --tag my_second_tag -- tag ~my_third_tag
The ~ will exclude any spec with those tags, so its often useful to do something like
rspec spec --tag ~long_runing

Related

What is a good schema for naming screenshots in selenium webdriver + capyabara

First pass: I name my screenshot "x".
Obviously that minimal setup only allows for 1 screenshot
I want to name the screenshots in a way that makes them unique and also reflect the usage.
I can make the filenname fairly unique with
output_directory = 'screenshots'
time = Time.new
page.save_screenshot("#{output_directory}/#{time}.png")
It's a bit ugly but I get
$ ls screenshots/
'019-04-13 07:07:50 -0400.png''
What would be good format to use that would meet the requirements of both unique and also descriptive. Could I include the scenario description somehow?
How could I end up with something like:
scenario_decsription_2019_04_19-08_55_20
The RSpec test definition methods and hooks (scenario, before, after, etc) all receive an optional parameter which is the test example itself. This allows you to get the description of the test, etc for use in naming your file
scenario "my test" do |example|
...
page.save_screenshot("#{example.full_description}.png")
end
Obviously you could transform the description in any way you want (convert spaces to underscores, etc).
Note: you may also want to look at Capybara.save_path which specifies what directory screenshots are stored in, if you don't want to prepend screenshots/ everywhere.
How about something like this?
scenario "#{scenario = 'user_clicks_the_dropdown'}" do
output_directory = 'screenshots'
time = Time.new
suffix = time.to_s(:db).gsub(/[\:\.\_\s]/,'_')
page.save_screenshot("#{output_directory}/#{scenario}_#{suffix}.png")
end

Better diffs with minitest

I'm looking at my test case results, and it's far to difficult to see where the one small failure in my test is coming from.
I'm dealing with reasonable sized data structures - and I don't want to change the to_s method so that it's slightly better for the minitest diff.
I've looked at the reporters but they don't seem to have anything like what I'm looking for. (I'm using ruby 1.9.3)
Is there any way that minitest or some library for minitest could highlight the part of the string that is different between two results?
Or is there something I'm missing that allows you to visually look at the diff more easily?
Edit: Example
Minitest::Assertion:
--- expected
+++ actual
## -1 +1 ##
-#<struct MyModule::Swipe id=0, lat=37.62996, lng=-122.42115, route=#<struct MyModule::Route id=17, bus_name="test_name", stops=[#<struct MyModule::Stop id=29, name="Cool Stop">]>, date_time="2015-10-29T11:05:02+00:00">
+#<struct MyModule::Swipe id=0, lat=37.62996, lng=-122.42115, route=#<struct MyModule::Route id=17, bus_name="test_name", stops=[#<struct MyModule::Stop id="29", name="Cool Stop">]>, date_time="2015-10-29T11:05:02+00:00">
Instead could show the line, and highlight in another colour the id="29" vs the id=29 only. Minitest seems to show the diff based on the lines printed.
pretty-diff
I had the same problem, and in case of invisible blank characters, this gem is still not good enough for debugging. I end up adding .inspect to both String that I passed to assert_equal in minitest test case.

Guard, how to temporally track specific file?

I'm using Guard gem
At some time of development I need to track only a specific file or several files but not an entire project.
Is there some handy way to temporarily track a particular file?
I know it can be done by modifying guard file but I don't think it's a neat solution.
Actually you can just use focus: true in the it statement for instance:
In your Spec file.
it "needs to focus on this!", focus: true do
#test written here.
end
Then in spec/spec_helper you need to add the config option.
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
end
Then Guard will automatically pick up test that is focused and run it only. Also the config.run_all_when_everything_filtered = true tells guard to run all of the tests when there is nothing filtered even though the name sounds misleading.
I find Ryan Bate's rails casts to be very helpful on Guard and Spork.
Perhaps groups will work for you?
# In your Guardfile
group :focus do
guard :ruby do
watch('file_to_focus_on.rb')
end
end
# Run it with
guard -g focus
I know you mentioned you don't want to modify the Guardfile, but adding a group would just need to be done once, not every time you switch from watching the project to a focused set and back.
Of course if the set of files you need to focus on changes, you'll need to change the args to watch (and maybe add more watchers), but I figure you'll have to specify them somewhere and this seems as good a place as any.
Alternately, if you really don't want to list the files to focus on in the Guardfile, you could have the :focus group read in a list of files from a separate file or an environment variable as suggested by David above. The Guardfile is just plain ruby (with access to the guard DSL), so it's easy to read a file or ENV variable.
If you use guard-rspec. You can do this.
Change your Guardfile rspec block so that is has something like this:
guard 'rspec', :cli => ENV['RSPEC_e'].nil? ? "": "-e #{ENV['RSPEC_e']}") do
# ... regular rspec-rails stuff goes here ...
end
Start Guard. And set RSPEC_e before. Like so...
RSPEC_e=here guard
Then whenever you change something only specs that have text "here" (set by RSPEC_e) in their description will be re-run.
You could permanently modify the guard file to check an environment variable of your choosing and behave differently if it is present. For example, access the variable ENV['FILE']. Then you can prepend your command for running guard with FILE=foo.rb whenever you want.

Ruby, regex, sentences

I'm currently building a code generator, which aims to generate boiler plate for me once I write the templates and/or translations, in whatever language I have to work with.
I have a problem with a regex in Ruby. The regex aims to select whatever is between {{{ and }}}, so I can generate functions according to my needs.
My regex is currently :
/\{\{\{(([a-zA-Z]|\s)+)\}\}\}/m
My test data set is:
{{{Demande aaa}}} => {{{tagadatsouintsouin tutu}}}
The results are:
[["Demande aaa", "a"], ["tagadatsouintsouin tutu", "u"]]
Each time the regex picks the last character twice. That's not exactly what I want, I need something more like this:
/\{\{\{((\w|\W)+)\}\}\}/m
But this has a flaw too, the results are:
[["Demande aaa}}} => {{{tagadatsouintsouin tutu", "u"]]
Whereas, I wish to get:
[["Demande aaa"],["tagadatsouintsouin tutu"]]
How do I correct these regexes? I could use two sets of delimiters, but it won't teach me anything.
Edit :
All your regex run against my data sample, so you all got a point.
Regex may be overkill, and probably are overkill for my purpose. So i have two questions.
First, do the regex keep the same exact indentation ? This should be able to handle whole functions.
Second, is there something fitter for that task ?
Detailled explanation of the purpose of this tool. I'm bored to write boiler plate code in php - symfony. So i wish to generate this according to templates.
My intent is to build some views, some controllers, and even parts of model this way.
Pratical example : In my model, i wish to generate some functions according to the type of an object's attribute. For examples, i have functions displaying correctly money. So i need to build the corect function, according to my attribute, and then put in , inside m output file.
So there is some translations which themselves need translations.
So a fictive example :
{{{euro}}} => {{{ function getMyAttributeEuro()
{
return formating($this->get[[MyAttribute]]);
} }}}
In order to stock my translations, should i use regex, like
I wish to build something a bit clever, so it can build most of the basic code with no bug. So i can work on interesting code.
You have one set of capturing parentheses too many.
/\{\{\{([a-zA-Z\s]+)\}\}\}/
Also, you don't need the /m modifier because there is no dot (.) in your regex whose behaviour would be affected by it.
I'm partial to:
data = '{{{Demande aaa}}} => {{{tagadatsouintsouin tutu}}}'
data.scan(/\{{3}(.+?)}{3}/).flatten.map{ |r| r.squeeze(' ') }
=> ["Demande aaa", "tagadatsouintsouin tutu"]
or:
data.scan(/\{{3}(.+?)}{3}/).flatten.map{ |r| [ r.squeeze(' ') ] }
=> [["Demande aaa"], ["tagadatsouintsouin tutu"]]
or:
data.scan(/\{{3}(.+?)}{3}/).map{ |r| [ r[0].squeeze(' ') ] }
=> [["Demande aaa"], ["tagadatsouintsouin tutu"]]
if you need the sub-arrays.
I'm not big on trying to everything possible inside the regex. I prefer to keep it short and sweet, then polish the output once I've found what I was looking for. It's a maintenance issue, because regex make my head hurt, and I stopped thinking of them as a macho thing years ago. Regex are a very useful tool, but too often they are seen as the answer to every problem, which they're not.
Some people, when confronted with a problem, think “I know,
I'll use regular expressions.” Now they have two problems.
-- Jamie Zawinski
You want non capturing groups (?:...), but here is another way.
/\{\{\{(.*?)\}\}\}/m
Just a shot
/\{\{\{([\w\W]+?)\}\}\}/
Added non-greedyness to your regex
Here this seems to work

How to make a word list from a text file in a more Ruby way?

I'd like to get a word list from a text file using Ruby. I found how to use regex to parse only words here, so I made a script like following:
src = File.open("text.txt")
word_list = []
src.each do |line|
word_list << line.downcase.split(/[^[:alpha:]]/).delete_if {|x| x == ""}
end
word_list.flatten!.uniq!.sort!
p word_list
And the following is a sample text file text.txt:
TextMate may be the latest craze for developing Ruby on Rails
applications, but Vim is forever. This plugin offers the following
features for Ruby on Rails application development.
Automatically detects buffers containing files from Rails applications, and applies settings to those buffers (and only those
buffers). You can use an autocommand to apply your own custom
settings as well.
Unintrusive. Only files in a Rails application should be affected; regular Ruby scripts are left untouched. Even when enabled, the
plugin should keep out of your way if you're not using its features.
Easy navigation of the Rails directory structure. gf considers context and knows about partials, fixtures, and much more. There are
two commands, :A (alternate) and :R (related) for easy jumping between
files, including favorites like model to migration, template to
helper, and controller to functional test. For more advanced usage,
:Rmodel, :Rview, :Rcontroller, and several other commands are
provided.
As a Ruby novice, I'd like to learn better (more clear, concise, and following conventions) solutions for this problem.
Thanks for any advices and corrections.
A more idiomatic code would be:
word_list = open("text.txt")
.lines
.flat_map { |line| line.downcase.split(/[^[:alpha:]]/).reject(&:empty?) }
.uniq
.sort
# I suppose you want each line and collect the results
word_list = File.open("text.txt").each_line.collect do |line|
# collecting is done via collect above, no need anymore
# .reject(&:empty?) calls .empty? on each element
line.downcase.split(/[^[:alpha:]]/).reject(&:empty?)
# you can chain on blocks as well
end.flatten!.uniq!.sort!
p word_list

Resources