I have some logs that need analyzing to check if the logs do not have abnormalities and are incorrect form so to speak.
I have generated a CSV file for it:
"timestamp","source","message
"2021-10-18T09:12:29.000Z","Storage","Storage apache: [18/Oct/2021:09:12:29 0800] 10.102.141.82 - GET /deviceManager/rest/
"2021-10-18T09:12:29.000Z","Storage","Storage apache: [18/Oct/2021:09:12:29 0800] 10.102.141.82 - GET /deviceManager/rest/
"2021-10-18T09:12:29.000Z","Storage","Storage apache: [18/Oct/2021:09:12:29 0800] 10.102.141.82 - GET /deviceManager/rest/
"2021-10-18T09:12:29.000Z","Storage","Storage apache: [18/Oct/2021:09:12:29 0800] 10.102.141.82 - GET /deviceManager/rest/
I use the CSV gem to parse/read this file and use an RSpec test to expect some value/text/time format etc. I have written the code below. It takes the rows from 8 to 12 for example and I want to expect a text called "Huawei" f.e in those rows.
RSpec.describe "Log parsing" do
it 'returns the source' do
table = CSV.read("Messages_result.csv")
puts arr = table.values_at(8..12)
arr.each do |rows|
expect(rows).to include('Huawei')
end
end
end
The problem I am getting is it always executes the expect for the first line but I want to parse/iterate through the whole CSV file and should as well show me for each line a result. My expect message will change of course but I just want to check first for a basic text like Huawei. Can somebody please show what I am doing wrong since each do should theoretically go through the complete rows and throw an expectation for each?
CodePudding user response:
You may want to do something like this ?
RSpec.describe "Log parsing" do
it 'returns the source' do
CSV.foreach("Messages_result.csv", :headers => true) do |row|
expect(row.to_h.values).to include("Storage")
end
end
end
Update
i want to parse/iterate through the whole csv file and should as well show me for each line a result.
Do you want to use Rspec as a logger? That's not possible, see Add a configuration option to continue on failure.
That said, by modifying a little the code, you can make Rspec check the whole file and show all the rows that fail your expect
:
RSpec.describe "Log parsing" do
CSV.foreach("Messages_result.csv", :headers => true) do |row|
it 'returns the source' do
expect(row.to_h.values).to include("Huawei")
end
end
end
outputs:
FF
Failures:
1) Log parsing returns the source
Failure/Error: expect(row.to_h.values).to include("Huawei")
expected ["2021-10-18T09:10:29.000Z", "Storage", "Storage apache: [18/Oct/2021:09:10:29 0800] 10.102.141.82 - GET /deviceManager/rest/"] to include "Huawei"
# ./Messages_result.rb:10:in `block (3 levels) in <main>'
2) Log parsing returns the source
Failure/Error: expect(row.to_h.values).to include("Huawei")
expected ["2021-10-18T09:11:24.000Z", "Storage", "Storage apache: [18/Oct/2021:09:11:24 0800] 10.102.141.82 -...../license/feature HTTP/1.1 python-requests/2.21.0 - - application/json - / gzip, deflate 200 49 0"] to include "Huawei"
# ./Messages_result.rb:10:in `block (3 levels) in <main>'
...
If you really need to output a message for each line of the CSV then you don't have any other choice than print it yourself. For example:
# get the output stream that Rspec is currently using
ostream = RSpec.configure { |c| c.output_stream }
# define a few colorization helpers
if ostream.tty?
def red str; "\e[31m#{str}\e[0m"; end
def green str; "\e[32m#{str}\e[0m"; end
else
def red str; str; end
def green str; str; end
end
RSpec.describe "Log parsing" do
it 'returns the source' do
ostream.puts
ostream.puts " -) Log parsing returns the source - details"
expected = "Huawei"
success = true
CSV.foreach("Messages_result.csv", :headers => true) do |row|
values = row.to_h.values
detail = "expected #{values} to include #{expected.inspect}"
ostream.print ' ' * 5
if values.include?(expected)
ostream.puts green("PASSED: #{detail}")
else
ostream.puts red("FAILED: #{detail}")
success = false
end
end
ostream.puts
ostream.flush
expect(success).to be(true)
end
end