Em uma aplicação Ruby on Rails, quando você precisa assegurar nos seus testes que a gravação de logs está sendo realizada com sucesso, não há a necessidade de abrir o arquivo físico de log, ler seu conteúdo e verificar se a informação que você deseja está lá.
Ao invés disso, você pode substituir a saída de escrita padrão do log por outra classe de stream, como a StringIO, onde você terá fácil acesso ao que for gravado no log durante o teste.

Log em inglês também é tronco, lenha.
Vamos ver um exemplo utilizando RSpec para testar a gravação de log de um método chamado do_something em uma classe modelo SomeModel.
require 'spec_helper'
describe SomeModel do
before(:each) do
@some_model = SomeModel.new
@log_stream = StringIO.new
@some_model.stub(:logger).and_return(Logger.new(@log_stream))
end
describe "#do_something" do
it "logs info" do
@some_model.do_something
@log_stream.string.should include("I am logging something")
end
end
end
Na linha 7, criamos uma instância de StringIO atribuindo à variável @log_stream. É nesse objeto que serão gravados todos os logs do nosso teste. Para isso, na linha 8, substituímos o logger original por um stub de Logger que faz referência à instância da classe StringIO que criamos.
Já na linha 14, a asserção do nosso teste verifica se o texto correto foi gravado no stream do log. O método StringIO#string retorna a string bruta, ou seja, o texto que foi gravado no stream.
A seguir está a implementação do método do_something:
class SomeModel < ActiveRecord::Base
def do_something
# some implementation
logger.info "I am logging something"
end
end
Para fazer testes de gravação de logs em controllers, a idéia é a mesma, basta apenas usar o stub no método logger do controller (linha 6):
require 'spec_helper'
describe SomeModelsController do
before(:each) do
@log_stream = StringIO.new
controller.stub(:logger).and_return(Logger.new(@log_stream))
end
describe "GET index" do
it "logs info" do
get :index
@log_stream.string.should include("Now logging in a controller")
end
end
end
class SomeModelsController < ApplicationController
def index
# implementation
logger.info "Now logging in a controller"
end
end
Se você precisa usar log em uma classe que não seja um modelo ou controller, não vai poder chamar o método logger diretamente. Por exemplo, a classe a seguir, foi criada dentro da pasta lib de uma aplicação Rails.
class CoolClass
def cool_method
logger.info "Cool log!"
end
end
Chamando o método cool_method teremos o seguinte erro:
> c = CoolClass.new
> c.cool_method
NameError: undefined local variable or method `logger’ for #<CoolClass:0×1e81bf0>
Resolver isso é simples, basta utilizar Rails.logger:
class CoolClass
def cool_method
Rails.logger.info "Cool log!"
end
end
E no teste para gravação de log o stub é feito na classe Rails (linha 8):
require 'spec_helper'
describe CoolClass do
before(:each) do
@cool_class = CoolClass.new
@log_stream = StringIO.new
Rails.stub(:logger).and_return(Logger.new(@log_stream))
end
describe "#cool_method" do
it "logs info" do
@cool_class.cool_method
@log_stream.string.should include("Cool log!")
end
end
end
Ruby, TDD Log, Rails, RSpec, Ruby, Ruby on Rails, TDD
Comentários