Load different files from let - ruby

Is there a way to load different files passed as arguments in Ruby let definition? This is the code that I sue to load file in rspec:
let(:xml_file) { File.read(File.join('spec', 'fixtures', 'xml', 'example1.xml')) }
I need something like this:
let(:xml_file) { File.read(File.join('spec', 'fixtures', 'xml', #{file})) }
Can you propose some solution?

Just make file name a variable and define it per describe/context
let(:xml_file) { File.read(File.join('spec', 'fixtures', 'xml', file_name)) }
context '1' do
let(:file_name) { 'foobar_1.xml' }
it 'test sth' do
xml_file # should be spec/fixtures/xml/foobar_1.xml
end
end
context '2' do
let(:file_name) { 'foobar_2.xml' }
it 'test sth' do
xml_file # should be spec/fixtures/xml/foobar_2.xml
end
end

If you need to use an specific file on each test, you can define another let on each context or describe section:
let(:xml_file) { File.read(File.join('spec', 'fixtures', 'xml', file))}
describe "first set of tests" do
let(:file) { "file_1.txt" }
end
describe "second set of tests" do
let(:file) { "file_2.txt" }
end

Related

NameError: uninitialized constant Parsers in RSpec

I'm trying to test simple class in my Ruby 2.5.0 app:
source/parsers/jira_parser.rb
module Parsers
class JiraParser
def initialize(event)
payload = event['body']
#event = JSON.parse(payload)
end
def call
{
reporter_email: reporter_email,
reporter_name: reporter_name,
ticket_number: ticket_number,
description: description
}
end
private
attr_reader :event
def reporter_email
event.dig('issue', 'fields', 'reporter', 'emailAddress')
end
# other methods from call are pretty much the same as `reporter_email`
With below specs:
spec/source/parsers/jira_parser_spec.rb
require 'spec_helper'
RSpec.describe Parsers::JiraParser do
describe 'call' do
subject(:hash_creation) { described_class.new(event).call }
let(:reporter_name) { 'john.doe' }
let(:reporter_email) { 'john.doe#example.com' }
let(:description) { 'This is a test description' }
let(:event) do
{
'body' => {
'issue': {
'key': 'TEST-Board-123',
'fields': {
'reporter': {
'displayName': reporter_name,
'emailAddress': reporter_email
},
'description': description
}
}
}
}
end
it { expect(hash_creation).to be_success }
end
end
But I've got an error:
NameError:
uninitialized constant Parsers
./spec/source/parsers/jira_parser_spec.rb:5:in `'
No examples found.
Should I add something to my rspec_helper to make it works?
Right now it's pretty basic:
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
I understand this is just Ruby, no Rails, hence there's no magic involved. You need to make a source file available in spec file, so you have to put on the top something like:
require_relative '../../../source/parsers/jira_parser
Hello I am still pretty new so this might help but I believe that you need to require JiraParser
require 'jira_parser'
require 'jira_parser/parser'
This might work but the error is because you are trying to use a parser that is not accessible in your current code.
Ok I figured out - all I had to do was to add -I source inside the .rspec file to will load all tested classes. So in my case .rspec will look like below:
.rspec
--require spec_helper
-I source

How to inspect CSV file columns inside RSpec test?

I really don't know how to inspect CSV file I created in my ROR App.
require "rails_helper"
require "shared_contexts/vcr/s3"
require "csv"
RSpec.describe ReportRuns::RunService do
describe "CSV columns" do
include_context "vcr s3 put csv"
let(:report_run) { create :report_run, report_template: report_template, created_by: user.id, mime_type: "csv" }
#let(:report_template) { create :report_template, template_structure: { module: "trial_members", filters: { trial_members: [trial_members.id] } } }
let(:report_template) { create :report_template, trial: trial }
let(:trial) { create :trial }
let(:user) { create :user }
let(:user_role) { create :user_role }
subject { described_class.new(report_run) }
before do
end
it do
get :index, format: :csv
p "response jee: #{response.body}"
p response.headers
p "report run: #{report_run.inspect}"
p "templejt: #{report_template.inspect}"
p "mime type: #{report_run[:mime_type]}"
#p "trila je: #{trial.inspect}"
p "users are: #{user.inspect}"
p "user roles su: #{user_role.inspect}"
is_expected.to be_truthy
expect(5).to match(5)
end
end
end
Use the CSV library to parse the body of the response. Then work with the CSV object.
csv = CSV.new(response.body)
You can also check the Content-type headers are correct, text/csv.

How do I bypass the arguments in a method for testing in rspec?

How do I use an allow to receive to bypass the arguments in the method for testing?
I have two hashes in my spec which I want to use for keys_1 and keys_2 but I need to bypass yaml_1 and yaml_2 because I don't currently have any files to read from. How would I do this?
compare_code_spec.rb
let(:main_hash) {
{ navigation:
{ about: 'About',
blog: 'Blog',
contributors: 'Contributors',
partners: 'Partners',
privacy: 'Privacy Policy'}
}
}
let(:second_hash) {
{ navigation:
{ about: 'About',
blog: 'Blog',
partners: 'Partners'}
}
}
describe '.compare' do
subject(:subject) { described_class.compare(locale_1, locale_2) }
it 'compares locales' do
expect(subject).to eq(result)
end
end
compare_code.rb
def compare(locale_1, locale_2)
yaml_1 = YAML.load(File.open(File.expand_path(locale_1)))
yaml_2 = YAML.load(File.open(File.expand_path(locale_2)))
keys_1 = flatten_keys(yaml_1[yaml_1.keys.first])
keys_2 = flatten_keys(yaml_2[yaml_2.keys.first])
end

Why is my rspec test doubling my objects?

This is one of those cases where my code is working but my test is failing and I need to know what I am doing wrong?
I have a Project class with an all method that just spits out instances of this class:
class Project
##all_projects = []
def initialize(options)
##all_projects << self
end
def self.all
##all_projects
end
end
Now Project.all works just fine but the spec I am writing doesn't.
context "manipulating projects" do
before do
options1 = {
name: 'Building house'
}
options2 = {
name: 'Getting a loan from the Bank'
}
#project1 = Project.new(options1)
#project2 = Project.new(options2)
end
it "can print all projects" do
Project.all.should eq([#project1, #project2])
end
The failure message I get is:
Project manipulating projects can print all projects
Failure/Error: Project.all.should eq([#project1, #project2])
expected: [Building house, Getting a loan from the Bank]
got: [Building house, Building house, Building house, Getting a loan from the Bank, Building house, Getting a loan from the Bank]
Here is the full spec in a gist: https://gist.github.com/4535863
What am I doing wrong? How can I fix it?
It is doubling the results because it runs the before block for each test, where the class attribute is modified (when two new projects are initialized), and (according to the gist) the test you're referring to is the second one.
To avoid the problem you'll need to reset ##all_projects in an after block:
after do
Project.class_variable_set :##all_projects, []
end
See also: How can I clear class variables between rspec tests in ruby
(Thanks to #iain for the suggestion to move the reset code to an after block rather than a before block.)
This doesn't use before blocks to set stinky instance variables.
describe Project do
let(:options1){
{
name: 'Building house',
priority: 2,
tasks: []
}
}
let(:options2) {
{
name: 'Getting a loan from the Bank',
priority: 3,
tasks: []
}
}
let(:project1) { Project.new(options1) }
let(:project2) { Project.new(options2) }
context "while starting up" do
subject { Project.new options1 }
its(:name) { should include('Building house') }
its(:tasks) { should be_empty }
end
context "manipulating projects" do
before :all do
Project.all.clear
end
subject { Project.all }
its(:count) { should be > 0 }
it { should eq [project1, project2] }
end
end

SGML replace tags and write to new and different file in Ruby

I have a very long SGML file which I need to convert to a another syntax, but for some reason my code don't work, when I get the output it is the exactly the same document, the code is as following:
#!usr/bin/env ruby
def replaceStrings(toChange)
##Remove Title tags and replace with the correct
toChange.gsub(/<title>/) { "=====" }
toChange.gsub(/<\/title>/) { "=====" }
##Image
toChange.gsub(/<graphic fileref="/) { "{{" }
toChange.gsub(/<\/graphic>/) { "|}}" }
toChange.gsub(/;" scale="60">/) { "" }
##Paragraphs
toChange.gsub(/<para>/) { "" }
toChange.gsub(/<\/para>/) { "" }
puts toChange
end
fileInput = ARGV[0]
fileOutput = ARGV[1]
document = File.readlines(fileInput)
puts fileInput
puts fileOutput
document.each { |e| replaceStrings(e)}
File.new(fileOutput, 'w')
File.open(fileOutput, 'w'){
|f| f.write(document)
}
As far as I can tell I do call the replaceString method, but am I missing something or doing some thing wrong?
NOTE: I am pretty new at Ruby
You want to use gsub!
Also, no need to use the block form:
toChange.gsub!(/<title>/, "=====")
Also, I don't think you need File new:
File.open(fileOutput, 'w') do |f|
f.write(document)
end

Resources