Trailblazer: Which step caused my operation to fail? - ruby

Given an operation like
class MyOperation < Trailblazer::Operation
step :do_a!
step :do_b!
def do_a(options, **)
false
end
def do_b(options, **)
true
end
end
and the result of run(MyOperation), how can I tell which step of the operation failed?
If the result object doesn't contain this info by default, what's a good way to add it?

There is this gem now which provides operation specific debugging utilities - https://github.com/trailblazer/trailblazer-developer
It allows you to see exactly which step raised the exception or which step caused the track to change from success to failure.
Trailblazer::Developer.wtf?(MyOperation, options)
It will print the trace of steps on STDOUT/Logger.

Related

How to raise timeout error in unittesting

This is first time i am touching ruby, so no sure about correct terminology. I have tried searching for mulitple things, but couldn't find a solution.
I have this code block
domain_response = MyDomain::Api::MyApi::Api.new(parameters: message.to_domain_object, timeout: 1000)
# :nocov:
case (response = domain_response.response)
when MyDomain::Api::MyApi::SuccessResponse
## do something
when Domain::ErrorResponses::TimeoutResponse
## do something.
now i am trying to testing TimeoutResponse, I have written(tried) this
it "when api call timesout" do
expect(MyDomain::Api::MyApi::Api).to{
receive(:new)
} raise_error(MyDomain::ErrorResponses::TimeoutResponse)
end
this gave me error that unexpected identifier.
I have also tried by not providing receive, and it gave me error that block is expected.
Whats the proper way to raise an error that i can test?
Update:
Here is where i am stuck now
it "when api call timesout" do
# 1
expect(MyDomain::Api::MyApi::Api).to(
receive(:new),
).and_return(domain_api_instance)
# 2
expect(domain_api_instance.response).to receive(:response).and_raise(Domain::ErrorResponses::TimeoutResponse)
expect(domain_api_instance.response).to eq(ApiError::Timeout)
end
But with this code i am getting this error
1) Rpc::Package::SubPackage::V1::PackageService#first_test testing when api call timesout
Failure/Error: expect(domain_api_instance.response).to receive(:response).and_raise(Domain::ErrorResponses::TimeoutResponse)
#<InstanceDouble(MyDomain::Api::MyApi::Api) (anonymous)> received unexpected message :response with (no args)

Validation Error in ODOO

How to stop raising validation error in ODOO 10
For example in project.py file I want to stop raising this validation error :
#api.constrains('date_start', 'date_end')
def _check_dates(self):
if any(self.filtered(lambda task: task.date_start and task.date_end and task.date_start > task.date_end)):
raise ValidationError(_('Error ! Task starting date must be lower than its ending date.'))
You can disable that warning by overriding the function. Try below code,
#api.constrains('date_start', 'date_end')
def _check_dates(self):
if any(self.filtered(lambda task: task.date_start and task.date_end and task.date_start > task.date_end)):
pass;
#raise ValidationError(_('Error ! Task starting date must be lower than its ending date.'))
Hope it will help you.

dynamic usage of attribute in recipe

I am trying to increment the value and use in another resource dynamically in recipe but still failing to do that.
Chef::Log.info("I am in #{cookbook_name}::#{recipe_name} and current disk count #{node[:oracle][:asm][:test]}")
bash "beforeTest" do
code lazy{ echo #{node[:oracle][:asm][:test]} }
end
ruby_block "test current disk count" do
block do
node.set[:oracle][:asm][:test] = "#{node[:oracle][:asm][:test]}".to_i+1
end
end
bash "test" do
code lazy{ echo #{node[:oracle][:asm][:test]} }
end
However I'm still getting the error bellow:
NoMethodError ------------- undefined method echo' for Chef::Resource::Bash
Cookbook Trace: ---------------
/var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb:3:in block (2 levels) in from_file'
Resource Declaration: ---------------------
# In /var/chef/cache/cookbooks/Oracle11G/recipes/testSplit.rb
1: bash "beforeTest" do
2: code lazy{
3: echo "#{node[:oracle][:asm][:test]}"
4: }
5: end
Please can you help how lazy should be used in bash? If not lazy is there any other option?
bash "beforeTest" do
code lazy { "echo #{node[:oracle][:asm][:test]}" }
end
You should quote the command for the interpolation to work; if not, ruby would search for an echo command, which is unknown in ruby context (thus the error you get in log).
Warning: lazy has to be for the whole resource attribute; something like this WON'T work:
bash "beforeTest" do
code "echo node asm test is: #{lazy { node[:oracle][:asm][:test]} }"
end
The lazy evaluation takes a block of ruby code, as decribed here
You may have a better result with the log resource like this:
log "print before" do
message lazy { "node asm test is #{node[:oracle][:asm][:test]}" }
end
I've been drilling my head solving this problem until I came up with lambda expressions. But yet just using lambda didn't help me at all. So I thought of using both lambda and lazy evaluation. Though lambda is already lazy loading, when compiling chef recipe's, the resource where you call the lambda expression is still being evaluated. So to prevent it to being evaluated (somehow), I've put it inside a lazy evaluation string.
The lambda expression
app_version = lambda{`cat version`}
then the resource block
file 'tmp/validate.version' do
user 'user'
group 'user_group'
content lazy { app_version.call }
mode '0755'
end
Hope this can help others too :) or if you have some better solution please do let me know :)

ExecJS: keeping the context between two calls

I'm currently trying to use ExecJS to run Handlebars for one of the product I work on (note: I know the handlebars.rb gem which is really cool and I used it for some times but there is issues to get it installed on Windows, so I try another homemade solution).
One of the problem I'm having is that the Javascript context is not kept between each "call" to ExecJS.
Here the code where I instantiate the #js attribute:
class Context
attr_reader :js, :partials, :helpers
def initialize
src = File.open(::Handlebars::Source.bundled_path, 'r').read
#js = ExecJS.compile(src)
end
end
And here's a test showing the issue:
let(:ctx) { Hiptest::Handlebars::Context.new }
it "does not keep context properly (or I'm using the tool wrong" do
ctx.js.eval('my_variable = 42')
expect(ctx.js.eval('my_variable')).to eq(42)
end
And now when I run it:
rspec spec/handlebars_spec.rb:10 1 ↵
I, [2015-02-21T16:57:30.485774 #35939] INFO -- : Not reporting to Code Climate because ENV['CODECLIMATE_REPO_TOKEN'] is not set.
Run options: include {:locations=>{"./spec/handlebars_spec.rb"=>[10]}}
F
Failures:
1) Hiptest::Handlebars Context does not keep context properly (or I'm using the tool wrong
Failure/Error: expect(ctx.js.eval('my_variable')).to eq(42)
ExecJS::ProgramError:
ReferenceError: Can't find variable: my_variable
Note: I got the same issue with "exec" instead of "eval".
That is a silly example. What I really want to do it to run "Handlebars.registerPartial" and later on "Handlebars.compile". But when trying to use the partials in the template it fails because the one registered previously is lost.
Note that I've found a workaround but I find it pretty ugly :/
def register_partial(name, content)
#partials[name] = content
end
def call(*args)
#context.js.call([
"(function (partials, helpers, tmpl, args) {",
" Object.keys(partials).forEach(function (key) {",
" Handlebars.registerPartial(key, partials[key]);",
" })",
" return Handlebars.compile(tmpl).apply(null, args);",
"})"].join("\n"), #partials, #template, args)
end
Any idea on how to fix the issue ?
Only the context you create when you call ExecJS.compile is preserved between evals. Anything you want preserved needs to be part of the initial compile.

Two apparently equal test cases coming back failed. What can cause that?

Below are a few lines from my test case. The first assertion comes back as false, but why? The second does not.
result=Parser.parse_subject(##lexicon.scan("kill princess"), Pair.new(:noun, "bear"))
assert_equal(Parser.parse_subject(##lexicon.scan("kill princess"), Pair.new(:noun, "bear")),Parser.parse_subject(##lexicon.scan("kill princess"), Pair.new(:noun, "bear")))
assert_equal(result,result)
Here is the actual error:
Run options:
# Running tests:
.F.
Finished tests in 0.004000s, 750.0000 tests/s, 1750.0000 assertions/s.
1) Failure:
test_parse_subject(ParserTests) [test_fournineqa.rb:30]:
Sentence:0x21ad958 #object="princess", #subject="bear", #verb="kill" expect
ed but was
Sentence:0x21acda0 #object="princess", #subject="bear", #verb="kill".
3 tests, 7 assertions, 1 failures, 0 errors, 0 skips
It looks like you have defined a class Sentence but have provided no way to compare two Sentence instances, leaving assert_equal comparing the identities of two objects to discover that they are not the same instance.
A simple fix would be something like:
class Sentence
def ==(sentence)
#subject == sentence.subject and
#verb == sentence.verb and
#object == sentence.object
end
end
The first assertion compares two different objects with the same content whereas the second assertion compares two identical objects. Apparently equal in this context means "identical objects". (Check the implementation.)

Resources