jbk
jbk

Reputation: 2202

How do I Rspec test a non instance or class method?

I have a simple script which I'm playing with (a Ruby caesars cypher implementation), none of my methods are written within a Module or Class. How can I write Rspec tests to call these non-instance/class lone type methods?

def cypher(string, factor)
  string_array = string.downcase.split('')
  ...
  string_array.each do |item|
    ...
  end
  puts cyphered_array_alpha.join
end

Method content omitted for brevity.

Test:

describe "#cypher" do
  it "should return characters adjusted by given index" do
    expect(cypher("abcd", 1)).to eql('bcde')
  end
end

Ive tried using {cypher()} without any joy.

Upvotes: 0

Views: 425

Answers (2)

mechnicov
mechnicov

Reputation: 15248

All Ruby methods are located in specific modules or classes

When you define method on top level you define this method in Object as private method. Therefore it is available in any object. Usually it is a bad idea

Probably it's better to use some container for your method (class or module) and test this class or module

Also it's better to define method without any output — just return some value. In this case you can use this method anywhere, not only in STDOUT (for example in the web app, telegram bots, etc.)

# lib/caesar_cypher.rb

module CaesarCypher
  module_function

  def encrypt(string, factor)
  end

  def decrypt(cypher, key)
  end  
end

And then

# spec/caesar_cypher_spec.rb

describe CaesarCypher do
  describe '.encrypt' do
    it 'encrypts string...' do
      expect(described_class.encrypt('abcd', 1)).to eq('bcde')
    end
  end

  describe '.decrypt' do
  end
end

Upvotes: 2

jbk
jbk

Reputation: 2202

I've learned – from this helpful RSpec cheatsheet, that there are some less commonly used, more 'advanced' RSpec matchers, one of which; output(...).to_stdout can be used to evaluate block output. Though not a full explanation of how to test non-instance or class methods (aka a singleton method perhaps?), this matcher worked in my case:

expect {cypher("abcd", 1)}.to output("zabc\n").to_stdout

Upvotes: 1

Related Questions