Rubocop RSpec Describes are failing - ruby

Actually i'm trying to fix that issues:
Do not use multiple top level describes - try to nest them.
The first argument to describe should be the class or module being tested.
I have eight tests in that format:
describe 'PublicanCreatorsCreate.init_docu_work' do
it 'accesses a directory and creates there an initial documentation' do
PublicanCreatorsCreate.init_docu_work(title, type, language, brand, db5)
Dir.exist?(title)
:should == true
end
end
But what is false? The first argument contains the tested class and method.

Normally such a describe would be written as:
describe PublicanCreatorsCreate, '.init_docu_work' do
or
describe PublicanCreatorsCreate do
describe '.init_docu_work' do
It sounds like rubocop-rspec is expecting the second form.

Related

Encountering: syntax error, unexpected tIDENTIFIER, expecting keyword_end

I'm creating a directed_graph class in Ruby to practice using RSpec. I keep getting the above error (at line 13, which is the line below with "eql(0)" on it).
I don't really understand the error, especially since this RSpec code looks very similar to other RSpec code I've written for other projects that works.
require "directed_graph"
include directed_graph
describe directed_graph do
describe ".vertices" do
context "given an empty graph" do
it "returns an empty hash" do
g = directed_graph.new()
expect(g.vertices().length()).to() eql(0)
end
end
end
end
EDIT: I believe the problem was (1) directed_graph was a class, and classes must start with uppercase letters (so I renamed is DirectedGraph), and (2) you're not supposed to write "include" for classes.
I fixed those two, and my code seems to be runnign fine for now. I'm going to leave this up here in case I missed something big.
I believe the code should look like this:
require "directed_graph"
include DirectedGraph
describe DirectedGraph do
describe ".vertices" do
context "given an empty graph" do
it "returns an empty hash" do
expect(directed_graph.new.vertices.length).to eql(0)
end
end
end
end
Let me explain why. First include usually includes Classes/Modules. Classes and modules in ruby are denoted with Capital Letters for each part of their name (also know as UpperCamelCase). When you describe a class in in rspec, you should also use UpperCamelCase. I also cleaned up the code a little bit to make it easier to read. You don't always need the () to denote a function. It is implied. But sometimes you do need it, for example with the expect function.

What Is the correct syntax for writing test definitions in Cucumber?

What is the actual syntax for writing step definitions in Cucumber? I have seen it being written in different ways. Is there no definite syntax? I know the anchors are not compulsory, but is there a basic rule?
I am new to Cucumber and will appreciate baby step information to help me understand the basics. Thanks guys!
I was planning to point you to online documentation, but the online documentation I know about (at cucumber.io and at relishapp.com) doesn't actually answer your question well. (It does contain many examples, though, and is well worth reading.)
In the Ruby implementation of Cucumber, step definition files are .rb files in the features/step_definition directory. They contain a series of calls to methods that each define an implementation of a Gherkin step. Here's an example:
Given /^there is a user named "(.*)"$/ do |username|
# code that creates a user with the given username
end
There are several methods that define steps: Given, When, Then, And and But. They all do exactly the same thing, and you can use any one to define any step. The best practice is to use the one that reads best with the step you're defining (never And or But).
The argument passed to the step-defining method is a regular expression intended to match one or more steps in Gherkin .feature files. The above example matches the following step:
Given there is a user named "Ade Tester"
("Ade Tester" could be anything).
The block passed to the step-defining method is run when Cucumber executes a step which the regular expression matches. It can contain any Ruby code you like.
Matching groups (enclosed in parentheses) in the regular expression are passed to the block as block parameters. The number of matching groups must match the number of block parameters, or you'll get an error. A common convention is to enclose matching groups that match strings in quotes to visually separate them from the fixed part of the step, as I did above, but this is purely convention and you can choose not to do it.
The regexp need not match the entire step by default. If you want a definition to match only the entire step you must enforce that in the regular expression, as I did in the example above with ^ and $. Do that unless you have a good reason not to. This step definition (without $)
Given /^there is a user named "(.*)"/ do |username|
create :user, username: username
end
would match
Given there is a user named "Ade Tester" on weekdays but "Dave Schweisguth" on weekends
which would probably be a bad idea. Worse, if you had definitions for both steps, Cucumber would not be able to tell which definition to use and you'd get an error.
In features/step_definitions/documentation.rb:
When /^I go to the "([^"]+)" documentation$/ do |section|
path_part =
case section
when "Documentation"
"documentation"
else
raise "Unknown documentation section: #{section}"
end
visit "/documentation/#{path_part}/topics"
end
Then /^I should see the "([^"]+) documentation"$/ do |section|
expect(page).to have_css('h2.doctag_title a', text: section)
end
These steps exercise a web application. They are about as simple as they can be while still being practical.
A good step definition should have in its block a single method call e.g.
When "Frank logs in" do
login user: #frank
end
Bad step definitions have lots of code in their block e.g
When "I login as Frank" do
visit root_path
fill_in login_email, with:
# lots of other stuff about HOW to login
...
end
Other bad step definitions use really complicated regex's with lots of arguments.
Terrible step definitions call other step definitions and do the things bad step definitions do.

Why RSpec runs examples in the order not as they're declared?

I'm using RSpec 2.99 and have the following simple spec file:
describe 'thing' do
context 'context' do
it 'one thing' do
# ...
end
it 'another thing' do
# ...
end
end
it 'without context' do
# ...
end
end
The output was:
$ bundle exec rspec test_spec.rb -fd
thing
without context
context
one thing
another thing
Finished in 0.00092 seconds
3 examples, 0 failures
I can't figure out why without context goes before context.
It contradicts with what's written in the documentation for --order:
[...] executes groups and examples in the order they are defined [...]
What am I missing here?
Update: on the same documentation page there's a notion:
Nested groups are always run from top-level to bottom-level [...]
Is this applicable in the given case? If so, it turns out I can't make RSpec to run examples precisely as they go in a spec file (leave aside the question why would I need it).
The documentation is inaccurate. When an example group runs, it first runs its examples, then recursively delegates to each of its child example groups. This means that the examples of a group will always run before its nested example groups, even if some nested group were defined first.
However, with --order defined, the items within each category will be run in defined order.
This is a subtlety that we didn't bear in mind when writing the docs (or even when naming the --order defined option).
As for what we should do about it...I'm going to put some thoughts about that on the issue you opened.

What is the semantics of this "do ... end"

I am new to Ruby and am learning from reading an already written code.
I encounter this code:
label = TkLabel.new(#root) do
text 'Current Score: '
background 'lightblue'
end
What is the semantics of the syntax "do" above?
I played around with it and it seems like creating a TkLabel object then set its class variable text and background to be what specified in quote. However when I tried to do the same thing to a class I created, that didn't work.
Oh yeah, also about passing hash into function, such as
object.function('argument1'=>123, 'argument2'=>321)
How do I make a function that accepts that kind of argument?
Thanks in advance
What you're looking at is commonly referred to as a DSL, or Domain Specific Language.
At first glance it may not be clear why the code you see works, as text and background are seemingly undefined, but the trick here is that that code is actually evaluated in a scope in which they are. At it's simplest, the code driving it might look something like this:
class TkLabel
def initialize(root, &block)
#root = root
if block
# the code inside the block in your app is actually
# evaluated in the scope of the new instance of TkLabel
instance_eval(&block)
end
end
def text(value)
# set the text
end
def background(value)
# set the background
end
end
Second question first: that's just a hash. Create a function that accepts a single argument, and treat it like a hash.
The "semantics" are that initialize accepts a block (the do...end bit), and some methods accepting string parameters to set specific attributes.
Without knowing how you tried to do it, it's difficult to go much beyond that. Here are a few, possible, references that might help you over some initial hurdles.
Ruby is pretty decent at making miniature, internal DSLs because of its ability to accepts blocks and its forgiving (if arcane at times) syntax.

Using RSpec, are constants within describes a big no-no?

I just spent ages trying to figure out why my specs were passing in isolation, but when running the controller and lib tests together, some specs were mysteriously failing. The culprit was this:
In one spec:
describe SomeThing do
CONSTANT_VALUE = "a value"
# ... examples etc ...
end
And in another:
describe AnotherThing do
CONSTANT_VALUE = "a different value"
# ... the rest is history
end
The values I'd assigned to these constants was leaking between my specs and causing unexpected behaviour. Am I supposed to use a let block for defining constants etc? Or something else?
Yes, let is the answer here.

Resources