# RSpec: How to generate test logs? I have tried but it re-writes it for every test

**URL:** <https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446>\
**Category:** Testing\
**Tags:** rspec\
**Created:** [May 3, 2020, 8:05am UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446 "2020-05-03T08:05:20Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 3, 2020, 8:05am UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/1 "2020-05-03T08:05:20Z")

</div>

I have created this small sample code [GitHub - jeevan1987cool/sample-rspec-logging: Sample example to generate logs](https://github.com/jeevan1987cool/sample-rspec-logging).

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](https://ruby-doc.org/core-2.5.0/IO.html#method-c-new-label-IO+Open+Mode) 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.

How can I fix this?

Thanks

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 3, 2020, 7:07pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/2 "2020-05-03T19:07:04Z")

</div>

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

```auto
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.

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 3, 2020, 7:39pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/3 "2020-05-03T19:39:55Z")

</div>

In this case if I run 10 tests then I will get logs of 10th test only. But making a logger a global variable sounds good. How can I do that?

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 3, 2020, 8:28pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/4 "2020-05-03T20:28:37Z")

</div>

> But making a logger a global variable sounds good. How can I do that?

> **[assignment - RDoc Documentation](https://docs.ruby-lang.org/en/2.7.0/syntax/assignment_rdoc.html#label-Global+Variables)**

You can do (in place of def logger):

```auto
$logger = Logger.new File.new('example.log', 'w')
$logger.level = Logger::INFO

```

And in your tests, instead of calling `logger`, call `$logger`

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 3, 2020, 8:29pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/5 "2020-05-03T20:29:25Z")

</div>

Let me try quickly and get back to you

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 3, 2020, 8:33pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/6 "2020-05-03T20:33:33Z")

</div>

I used below snippet in `spec_helper.rb`

```
        def logger
          @logger = Logger.new File.new('example.log', 'w')
          @logger.level = Logger::INFO
          @logger
        end

```

and this is 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
    @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
```

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 4, 2020, 1:49am UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/7 "2020-05-04T01:49:34Z")

</div>

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.

You want to use $, to make a ‘global variable’.

This link: [assignment - RDoc Documentation](https://docs.ruby-lang.org/en/2.7.0/syntax/assignment_rdoc.html)  
explains the different kinds of variable.

What I was suggesting was:

1. in spec\_helper.rb, delete the def logger … end method. Replace with

```auto
$logger = Logger.new File.new('example.log', 'w')
$logger.level = Logger::INFO

```

1. then in your specs use:

```auto
    $logger.info 'passed'

```

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 4, 2020, 6:30am UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/8 "2020-05-04T06:30:52Z")

</div>

> [@pcl](#):
>
> $logger = Logger.new File.new(‘example.log’, ‘w’) $logger.level = Logger::INFO

It worked 😃

How can I see logs both in console and in log file?

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 4, 2020, 5:26pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/9 "2020-05-04T17:26:39Z")

</div>

> 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](https://docs.ruby-lang.org/en/2.7.0/Logger.html)

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 4, 2020, 6:35pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/10 "2020-05-04T18:35:35Z")

</div>

I changed with below snippet in `spec_helper.rb`

```auto
 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

```auto
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

```auto
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

```

line 15 is where I initialize the constructor

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 5, 2020, 12:36am UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/11 "2020-05-05T00:36:17Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Jeeva](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/e99b99/32.png) [@Jeeva](https://www.ruby-forum.com/u/Jeeva)\
**Post date:** [May 9, 2020, 12:06pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/12 "2020-05-09T12:06:34Z")

</div>

Now I have created a separate class for logger

```
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.

---

<div class="post-metadata">

**Author:** ![pcl](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ecae2f/32.png) [@pcl](https://www.ruby-forum.com/u/pcl)\
**Post date:** [May 12, 2020, 4:48pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/13 "2020-05-12T16:48:57Z")

</div>

Read the first two lines of `def logger`:

```auto
    @log_it = Logger.new(STDOUT)
    @log_it = Logger.new('example.log', level: Logger::INFO)

```

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:

```auto
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.

---

<div class="post-metadata">

**Author:** ![michellesans142](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/d78d45/32.png) [@michellesans142](https://www.ruby-forum.com/u/michellesans142)\
**Post date:** [November 4, 2021, 12:49pm UTC](https://www.ruby-forum.com/t/rspec-how-to-generate-test-logs-i-have-tried-but-it-re-writes-it-for-every-test/259446/14 "2021-11-04T12:49:18Z")

</div>

Create test logs for QA is great effort to list down things in a proper format. Get a [remote QA engineer in the USA](https://scrumteams.us/quality-assurance-engineering) for testing your website.
