Obligatory sorry if I'm being a noob but... I'm pretty new to rspec/ruby etc and I'm struggling to figure a few things out. Given the following rspec-puppet snippet:
if os == 'Ubuntu'
let(:facts) do
{
architecture: 'amd64',
operatingsystem: 'Ubuntu',
}
end
it { is_expected.to contain_service('docker').with_hasrestart('true') }
context 'It should include default prerequired_packages' do
it { is_expected.to contain_package('cgroup-lite').with_ensure('present') }
it { is_expected.to contain_package('apparmor').with_ensure('present') }
end
end
We've got these functions(objects?) like contain_service() and contain_package() that seem to have methods like with_hasrestart and with_ensure. What I'm trying to understand is, what are these functions? Are they part of rspec-puppet? I can't seem to find them in GitHub, and the docs don't really explain it. I'm trying to find all the available methods for each to better understand this all - and the source code would be great. Can anyone offer up some info/docs that explain it please?
Many thanks,
Dave
Edit: Looks like I didn't RTFM enough. It appears these are "matchers" and searching for contain_package in the code would never work.
Answering my own post, but I doubt anyone will actually need this.
These are "matchers", specifically a generic one here. They're part of the rspec-puppet package: https://github.com/rodjek/rspec-puppet/blob/master/lib/rspec-puppet/matchers/create_generic.rb
You can essentially do contain_<puppet resource> and those methods like with_ensure are like with_<resource parameter>.
Related
Probably a stupid question but I was following along this article and came across a bit of code I couldn't quite grasp. Here it is:
class CreateArticle
attr_reader :validate_article, :persist_article
def initialize(validate_article, persist_article)
#validate_article = validate_article
#persist_article = persist_article
end
def call(params)
result = validate_article.call(params)
if result.success?
persist_article.call(params)
end
end
end
More specifically, the problematic line is this:
if result.success?
Here's my problem with it: where did the success? method come from? It's not default in Ruby, and result is a local variable, so it should be nearby. But even if it's just omitted in the code sample, where would it have to be defined for that line to work? Everywhere I tried to define it just gave me an 'undefined method' error.
For example, I tried to define it both in the CreateArticle class and in the (only alluded to) ValidateArticle class, the obvious culprits, but no dice.
Update:
The reason I ask is not so much about what success? does as it is because I'm interested in using the pattern in my code. So, for example, my version of the success? method could be just checking whether a value got updated, or an item was inserted into an array. For example, let's say it's just this:
def success? # or self.success?
return true
end
Problem is, I can find no place where I can put this that works. I even created a module just for it and included it into the class, and still it doesn't work (it just returns 'undefined method'). So I'm still at a loss as to where I would have to define such a method so that it would work the way it looks like it should.
It's a method that comes with rails. It checks.for a server response with a 200 code. If it gets a 200 code it returns true else it returns false. Read the rails API docs about it... https://apidock.com/rails/v3.2.3/ActiveResource/Response/success%3F
Actually . success? is a built in ruby method. Check here. What it actually does is checking Stat and returns a boolean.
I did some more digging around the blog and from what I found I suspect that the code is probably making use of the dry-monads gem:
You can explicitly check the type by calling failure? or success? on a monadic value.
It's not explicit in the code excerpt but it's the only thing that makes sense.
ActiveRecord model: How to sort and be case insensitive?
After searching Google and trying a bunch of SO solutions, nothing seems to work and many other solutions are not as elegant as I would expect (they require invoking other methods explicitly rather than just work as a built-in-default, etc.).
This statement is what I like in its simplicity. The problem is that it is case sensitive:
default_scope -> { order(alias: :asc) }
Here are some solutions that I got from Google and SO:
1. default_scope -> { |alias| where(alias: alias.downcase) }
2. scope lambda { |email| where(email: alias.downcase) }
3. default_scope order: 'lower(alias)'
4. default_scope -> { order(lower(alias: :asc)) }
5. default_scope -> { order(lower(:alias) :asc) }
None of these solutions work: most generate errors. Perhaps this is because I am on Rails 5.0.2 and these are designed for old versions? I don't know.
In Ruby, at my stage of development, it is the simple things that trip me up. Thanks for your help.
This solution here does work. After getting to this point, this is rather obvious but what throws me off is the strange answers that were recalled in the original question that were found by researching this problem that absolutely don't work.
default_scope -> { order('lower(alias) asc') }
I am reading the 'Better specs' page, and in one of the examples it says:
context 'when logged in' do
it { is_expected.to respond_with 200 }
end
context 'when logged out' do
it { is_expected.to respond_with 401 }
end
And I don't recognize this. I usually would do:
context 'when logged out' do
it 'responds with a 401' do
expect(response).to eq(401)
end
end
What is that syntax?
This is something introduced heavily in Rspec 3.XX. It's under the one line syntax guides as outlined here
RSpec supports a one-liner syntax for setting an expectation on the
subject. RSpec will give the examples a doc string that is auto-
generated from the matcher used in the example. This is designed
specifically to help avoid duplication in situations where the doc
string and the matcher used in the example mirror each other exactly.
When used excessively, it can produce documentation output that does
not read well or contribute to understanding the object you are
describing.
This comes in two flavors:
is_expected is defined simply as expect(subject) and is designed for
when you are using rspec-expectations with its newer expect-based
syntax.
it { is_expected.to respond_with 200 }
that is more readable.
Why you added description if you can read it from test.
Your code should be simple, smart and readable in the same time...
but if you realy want, you can add even novel... up to you :)
I have a doubt about how to test a simple CSV importer without using the its(:...) clause.
In RSpec 2.x, my approach was to set the imported object as the subject of my spec, and then test each attribute in a its(...) block. It was an acceptance-like test, but it served me well, and I didn't want to unit test the library I used to do my CSV parsing, as it was really a trivial implementation, so I was ok with an end-to-end test.
Now, with RSpec 3, I can make this spec pass with transpec, but I read the explanation about why the its block has been removed and I think RSpec 3 is suggesting a different approach, right? So how would you test that?
I don't think a lot of ugly blocks like this
describe '#email' do
subject { super().email }
it { is_expected.to eq("john_doe#email.com") }
end
are any better than
its(:email) { should == "john.doe#email.com" }
as they do exactly the same thing.
I've read that you need to test "behaviour", but how about acceptance tests? What's the suggested way to go here?
Thanks!
From what I understand, Myron suggests using rspec-given for a one-liner rich test suite. Using this package, your tests will look something like this:
Given(:email) { subject.email }
context "sign up" do
When { subject.sign_up(email: "john.doe#email.com") }
Then { email == "john.doe#email.com" }
end
While the its functionality has been removed from rspec-core, it has been put into an includable gem, rspec-its.
https://github.com/rspec/rspec-its
I would just include this gem and keep writing tests the way you have been - I find them the most readable.
ps. Unrelated but I would also always use eq instead of == in specs :)
I am looking at some code that looks like the following
if (soap_begin_serve(pImpl))
{
if (pImpl->error >= SOAP_STOP)
{
// TODO.
}
return pImpl->error;
}
and trying to figure out what to do in the TODO section there. Any ideas on what SOAP_STOP means?
There's a few clues to what SOAP_STOP does scattered about the various gSOAP support sites. The best clues are here and here. It appears that any gSOAP error from 1000 on up is meant to tell the gSOAP engine to stop further processing.