2

I am trying to add logging to a simple rspec test. I am using Watir to drive Chrome within the spec and this works fine. I am unable to get logs using the "Logger" library.

This is my spec:

require 'rubygems'
require 'watir-webdriver'
require 'rspec'
require 'logger'

describe 'ui tests' do
  let(:browser) { browser ||= Watir::Browser.new :chrome }

  let(:log) {
    log = Logger.new(STDOUT)
    log = Logger.new('watir.tests.log', 'daily')
    log.level = Logger::DEBUG
  }

  before {
    browser.goto 'http://translate.google.com'
  }
  after { browser.close }

  context 'simple tests' do
    it 'simple test' do
      log.info("Running simple test")
      browser.text_field(:id => "source").set("ost")

      # actual test/asserts here

    end
  end
end

The problem is that I am unable to call any logging method such as log.info inside the example. I get this error:

Failures:

  1) ui tests simple tests simple test
Failure/Error: log.info("Running simple test")
NoMethodError:
  undefined method `info' for 0:Fixnum

Why is this failing? Is it a scope issue? If I comment out the log.info the spec runs fine. I can use any methods on the "browser" object (for example, the call to browser.text_field) inside the example without a problem.

Where I am going wrong?

1
  • 1
    Your let(:log) block does not return the Logger instance. Simply append a line with log before the closing } Commented Aug 9, 2016 at 16:24

1 Answer 1

6

The value of log is the last thing evaluated inside the let(:log) { } block, which is Logger::DEBUG. This constant just corresponds to the Fixnum 0, and there's no method called info for 0. Try this instead:

let(:log) { 
  Logger.new(STDOUT).tap { |l| l.level = Logger::DEBUG }
}

By the way, what are you trying to do with setting log = Logger.new(STDOUT) and then immediately reassigning log = Logger.new('watir.tests.log', 'daily')?

Sign up to request clarification or add additional context in comments.

6 Comments

I'm trying to get logging on both STDOUT and also to a file. I guess this isn't the right way to do this? I'm coming from log4j where you have appenders, and am (quite obviously) new to ruby.
Your solution works, but I can't understand the functional programming magic. Can you post a link to an explanation of what the feature is and how it works?
let(:foo) { do_stuff } is essentially equivalent to def foo; @foo ||= do_stuf; end. foo.tap { |bar| do_stuff } is a little harder, but it's often the same as bar = foo; do_stuff; foo;.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.