The issue with this is that it creates a new log file for every test. I have two tests in spec/first_test.rb. I have tried IO Open Modes also to fix it but none worked. Either it creates a new log file or keeps appending in the previous file.
However, what I am looking for is 1 file for an e2e execution. So if one e2e execution has 20 tests, then there won’t be 20 log files, but each test’s logs will be appended one below the other.
This appears to be a file-handling issue. Your tests call logger every time they want to write a message, and this is making a new file each time it is called, erasing any previous messages.
What if you make the file appendable: ‘a’ instead of ‘w’ and delete the logfile before the first run of the program: you should then get only that run’s messages in the log file.
e.g. in spec_helper.rb
BEGIN {
File.delete('example.log') if File.exist?('example.log')
}
def logger
logger = Logger.new File.new('example.log', 'a')
logger.level = Logger::INFO
logger
end
Another way, given you are writing to the same logfile, is make the logger a global variable, and refer to it directly instead of calling the logger method each time.
require_relative 'spec_helper'
describe 'test_feature', tms_1: 'QA-123', tms_2: 'QA-124' do
it 'test_case_1' do
expect(20).to be > 19
@logger.info 'Info Passed ********************'
end
it 'test_case_2' do
expect(21).to be > 19
@logger.info 'Info Failed ********************'
end
end
but it is giving error
NoMethodError:
undefined method `info' for nil:NilClass
That’s the wrong type of variable: @ introduces an ‘instance variable’, as in a field of a class. The class of your test is not that of spec_helper, hence you are getting nil.
How can I see logs both in console and in log file?
I think you need to create two logger instances, and write to them separately, if you want output in two places.
You can see the constructors in the documentation: class Logger - RDoc Documentation
def custom_logger
def initialize
$logger = Logger.new(STDOUT)
end
$logger = Logger.new('example.log', level: Logger::INFO)
$logger.level = Logger::INFO
$logger
end
and changed my spec file
require_relative 'spec_helper'
describe 'test_feature', tms_1: 'QA-123', tms_2: 'QA-124' do
it 'test_case_1' do
expect(20).to be > 19
custom_logger.info 'Info Passed ********************'
end
it 'test_case_2' do
expect(21).to be > 19
custom_logger.error 'Info Failed ********************'
end
end
it works but gives warning also
spec/spec_helper.rb:15:warning: redefining Object#initialize may cause infinite loop
spec_helper.rb:15: warning: redefining Object#initialize may cause infinite loop
what is your ‘initialize’ method supposed to be initializing? it is inside another method, and so will simply be declared at the top level - you are getting a warning about redefining an existing method because the top level is implicitly in the class Object and initialize is a method in that class.
class LoggerUtil
def initialize()
@log_it = Logger.new(STDOUT)
end
def logger
@log_it = Logger.new(STDOUT)
@log_it = Logger.new('example.log', level: Logger::INFO)
@log_it.level = Logger::INFO
@log_it
end
end
spec_helper.rb
def custom_logger
log = LoggerUtil.new()
log
end
test_class.rb
require_relative 'spec_helper'
require_relative '../helper/logger_util'
describe 'test_feature', tms_1: 'QA-123', tms_2: 'QA-124' do
it 'test_case_1' do
expect(20).to be > 19
custom_logger.logger.info 'Info Passed '
end
it 'test_case_2' do
expect(21).to be > 19
custom_logger.logger.error 'Info Failed'
end
end
This time also, it only creates a file but doesn’t print anything in the terminal. Please take a look.
You set the @log_it variable to one value (a logger that will write to STDOUT), and then change its value to a logger that will write to a file. (This code also makes your setting of @log_it in initialize redundant, because it gets changed every time logger is called.)
It’s as if you wrote:
x = 1
x = 2
Only the second value is preserved in the variable.
If you want to use two loggers, you will have to create and use two different loggers, stored in different variable names. Make logger1 STDOUT and logger2 output to a file, for instance.