Ruby - yoss123/test-automation-repo GitHub Wiki

Ruby's tutorial for beginners Another Ruby's tutorial for beginners Another Ruby's tutorial for beginners including How to instal Ruby on Rails with all the dependencies


Active record as an ORM (Object Relational Mapping) framework

Active Record basics tutorial


FactoryGirl (earlier version of FactoryBot)

Getting started with Factory Girl

On October 24th, 2017 the ThoughtBot team renamed their popular Ruby testing library FactoryGirl to FactoryBot.

Example 1:

factory :user do
  first_name "Joe"
  last_name  "Blow"
  email { "#{first_name}.#{last_name}@example.com".downcase }
end

create(:user, last_name: "Doe").email
# => "[email protected]"

RSpec - mocks

Example 1 - stubbing the result of a method

allow(SomeObject).to receive(:SomeObject_method).and_return(return_value_to_stub)
# The 'SomeObject_method' method won't be executed (for example, if we want to bypass the call for REST API executed in that method),
# instead it will return 'return_value_to_stub'
# The code that will follow the above code will return 'return_value_to_stub' every time we call 'SomeObject.SomeObject_method' (mocking)

Example 2 - stubbing the result of a method + asserting that this method was called in the test

describe SomeObjectToTest do
  context 'validtion' do

    let!(:command) do
      SomeObjectToTest.new
    end

    before(:each) do
      # The next 'expect' is validating that 'SomeObject_method' is being called only once
      expect(SomeObject).to receive(:SomeObject_method).exactly(1).times.and_return(return_value_to_stub)
      command.execute # while this execute method is calling SomeObject_method
    end

    it 'disables account sso' do
      # running some test here
    end
  end
end

Example 3 (stub_const - sample_1 ; sample_2):

# sample_1.rb => all tests are passing
FOO = 7

describe "stubbing FOO" do
  it "can stub FOO with a different value" do
    stub_const("FOO", 5)
    FOO.should eq(5)
  end

  it "restores the stubbed constant when the example completes" do
    FOO.should eq(7)
  end
end
# sample_2.rb
class CardDeck
  SUITS = [:Spades, :Diamonds, :Clubs, :Hearts]
  NUM_CARDS = 52
end

fake_class = Class.new
stub_const("CardDeck", fake_class)
CardDeck # => fake_class
CardDeck::SUITS # => raises uninitialized constant error
CardDeck::NUM_CARDS # => raises uninitialized constant error

stub_const("CardDeck", fake_class, :transfer_nested_constants => true)
CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts]
CardDeck::NUM_CARDS # => 52

stub_const("CardDeck", fake_class, :transfer_nested_constants => [:SUITS])
CardDeck::SUITS # => [:Spades, :Diamonds, :Clubs, :Hearts]
CardDeck::NUM_CARDS # => raises uninitialized constant error

Example 4 - stubbing requests

describe "Examples" do

  context 'External request' do
    it 'queries FactoryBot contributors on GitHub' do
      uri = URI('https://api.github.com/repos/thoughtbot/factory_bot/contributors')

      stub_request(:get, "https://api.github.com/repos/thoughtbot/factory_bot/contributors").
        with(
          headers: {
            'Accept'=>'*/*',
            'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
            'Host'=>'api.github.com',
            'User-Agent'=>'Ruby'
          }).
        to_return(status: 200, body: "", headers: {})

      response = Net::HTTP.get(uri)

      expect(response).to be_an_instance_of(String)
    end
  end
end

RSpec

RSpec's tutorial

Example 1:

# dog.rb
class Dog
  def initialize(hunger_level: 0)
    @hunger_level = hunger_level
  end

  def bark
    "Woof!"
  end

  def feed
    @hunger_level = 0
  end

  def hungery?
    @hunger_level > 5
  end
end
# dog_spec.rb
require 'rspec'
require_relative './dog'

RSpec.describe "Dog" do

  describe '#bark' do
    it 'returns the "Woof!"' do
      dog=Dog.new
      expect(dog.bark).to eql('Woof!')
    end
  end

  describe '#feed' do
    it 'is no longer hungry' do
      dog_to_feed=Dog.new
      dog_to_feed.feed
      expect(dog_to_feed.hungery?).to eql(false)
    end
  end

  describe '#hungry?' do
    context 'when hunger_level is more than 5' do
      it 'returns true' do
        hungry_dog= Dog.new(hunger_level: 7)
        expect(hungry_dog.hungery?).to eql(true)
      end
    end

    context 'when hunger_level is 5 or less' do
      it 'returns false' do
        not_hungry_dog= Dog.new(hunger_level: 5)
        expect(not_hungry_dog.hungery?).to eql(false)
      end
    end
  end

end

Example 2: (let())

describe Thing do
  let(:thing) { Thing.new }
  it “does something” do
    thing.do_something
  end
  describe “different case” do
    let(:thing) { Thing.new(case: "different") }
    it “does something else” do
      thing.do_something_else
    end
  end
end

Example 3: (it & specify are same methods)

# array_spec.rb
require 'rspec'

describe "Array" do

  describe "with 3 items" do
    before { @arr = [1,2,3]}

    specify {@arr.should_not be_empty}
    specify {@arr.count.should eq(3)}
  end

  describe "Array" do
    describe "with 3 items" do
      subject {[1,2,3]}

      it { should_not be_empty}
    end
  end
end

Example 4 (before & after):

describe "Examples" do

  context 'before and after example' do

    before(:all) do
      puts "before ALL print"
    end

    before(:each) do
      puts "before EACH print"
    end

    it '1st print' do
      puts "1st test print"
    end

    it '2nd print' do
      puts "2nd test print"
    end

    after(:all) do
      puts "after ALL print"
    end

    after(:each) do
      puts "after EACH print"
    end
  end
end
before ALL print
before EACH print
1st test print
after EACH print
.before EACH print
2nd test print
after EACH print
.after ALL print

Example 5 (shared_examples & it_behaves_like):

require "set"

RSpec.shared_examples "a collection object" do
  describe "<<" do
    it "adds objects to the end of the collection" do
      collection << 1
      collection << 2
      puts "Collection of type " + collection.class.to_s + " elements are: " + collection.to_s
      expect(collection.to_a).to match_array([1, 2])
    end
  end
end

RSpec.describe Array do
  it_behaves_like "a collection object" do
    puts "In it_behaves_like a collection object with an Array"
    let(:collection) { Array.new }
  end
end

RSpec.describe Set do
  it_behaves_like "a collection object" do
    puts "In it_behaves_like a collection object with a Set"
    let(:collection) { Set.new }
  end
end
In it_behaves_like a collection object with an Array
In it_behaves_like a collection object with a Set
Collection of type Array elements are: [1, 2]
.Collection of type Set elements are: #<Set: {1, 2}>

The difference between let and let!

Click here to get explanation for the next examples

describe GetTime do
  let(:current_time) { Time.now }

  it "gets the same time over and over again" do
    puts current_time # => 2018-07-19 09:35:29 +0300
    sleep(3)
    puts current_time # => 2018-07-19 09:35:29 +0300
  end

  it "gets the time again" do
    puts current_time # => 2018-07-19 09:35:32 +0300
  end
end
describe "GetTime" do
  let!(:current_time) { Time.now }

  before(:each) do
    puts Time.now # => 2018-07-19 09:57:52 +0300
  end

  it "gets the time" do
    sleep(3)
    puts current_time # => 2018-07-19 09:57:52 +0300
  end
end

Debugging via terminal (byebug)

To debug via terminal we need to install byebug with the next command "gem install byebug" running it from the project directory.

Now we need to add in our code a requirement for "byebug" and breakpoints like in the next example:

# dog.rb
class Dog
  def bark
    "Woof!"
  end
end
# dog_spec.rb
require 'byebug'
require 'rspec'
require_relative './dog'

describe Dog do
   describe '#bark' do
      it 'returns the "Woof!"' do
         dog=Dog.new
         byebug
         expect(dog.bark).to eql('Woof!')
      end
   end
end

Then we run the test file: rspec spec/controllers/dog_spec.rb

Then in the prompt we can see the object values by printing the object name, for example: dog we can also call methods by printing them, for example: dog.bark we can skip to the next line with 'n' (like f8 when debugging Java/Python) we can step into a function in the current line with 's' (like f9) we can continue running until the next breakpoint with 'c' (like f9) we can continue running to the end (skipping breakpoints) with 'c!' To exit the debug mode we simply print "exit()"


My code:

  • (csv-editor) csv-paginator-py/tests/test_combine.py
  • frontend/spec/commands/disable_account_sso_spec.rb