0

I am writing one apache log parsing script which return this output

'remote_host': '192.168.0.1', 'apache_status': '403', 'data_transfer': '3985'

Now to test this script I am writing unittest using pytest

import logparsing_apache
def test_final_report():
    output = logparsing_apache.final_report('192.168.0.1 - - [23/Apr/2017:05:54:36 -0400] "GET / HTTP/1.1" 403 3985 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"')
assert output == "'remote_host': '192.168.0.1', 'apache_status': '403', 'data_transfer': '3985'"

While running this script, its failing with this error

test_logparsing_apache.py:4: 
logparsing_apache.py:25: in final_report
line_dict = apache_output(line)
line = '1'
def apache_output(line):
    split_line = line.split()
    return {'remote_host': split_line[0],
          'apache_status': split_line[8],
            'data_transfer': split_line[9],
    }
E       IndexError: list index out of range
 logparsing_apache.py:18: IndexError

 1 failed,  in 0.03 seconds 

As my script return dictionary how to verify its output using assert?

Script:

import sys

def apache_output(line):
    split_line = line.split()
    return {'remote_host': split_line[0],
            'apache_status': split_line[8],
            'data_transfer': split_line[9],
    }


def final_report(logfile):
    for line in logfile:
        line_dict = apache_output(line)
        print(line_dict)


if __name__ == "__main__":
    if not len(sys.argv) > 1:
        print (__doc__)
        sys.exit(1)
    infile_name = sys.argv[1]
    try:
        infile = open(infile_name, 'r')
    except IOError:
        print ("You must specify a valid file to parse")
        print (__doc__)
        sys.exit(1)
    log_report = final_report(infile)
    print (log_report)
    infile.close()
jordanm
  • 33,009
  • 7
  • 61
  • 76
Prashant Lakhera
  • 850
  • 7
  • 13
  • See https://docs.pytest.org/en/latest/assert.html#assertions-about-expected-exceptions – Peter Wood May 05 '17 at 06:26
  • 1
    Possible duplicate of [How to properly assert that an exception gets raised in pytest?](http://stackoverflow.com/questions/23337471/how-to-properly-assert-that-an-exception-gets-raised-in-pytest) – Peter Wood May 05 '17 at 06:27
  • 1
    Your error and you question are unrelated – jordanm May 05 '17 at 06:27

1 Answers1

0

The reason for your error is because your final_report function is expecting a file object, not a string. Because of this, your final_report function ends up iterating over each character in the string. What ends up getting passed to apache_output is the string "1".

You can fix your current exception by passing a list instead of a string in your test:

output = logparsing_apache.final_report(['192.168.0.1 - - [23/Apr/2017:05:54:36 -0400] "GET / HTTP/1.1" 403 3985 "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"'])

If you prefer, you can also use the mock library to create a file-like object instead.

For your comparison, you can assert dictionaries are equal, but you need to actually make it a dictionary instead of a string:

assert output == {'remote_host': '192.168.0.1', 'apache_status': '403', 'data_transfer': '3985'}
jordanm
  • 33,009
  • 7
  • 61
  • 76
  • On a side note, you are probably better off using an existing library for parsing the log lines: https://pypi.python.org/pypi/apache-log-parser/1.6.2 – jordanm May 05 '17 at 06:36