I am new to Python and PyTest. I wrote a program that calculates the lines of code from another Python file. The source code is the following:
import os.path
import sys
def main():
print(count_loc(is_input_valid(sys.argv)))
def is_input_valid(cl_arg)->str:
if len(cl_arg) == 2:
if cl_arg[1][-3:] == '.py':
if os.path.isfile(cl_arg[1]):
filename = cl_arg[1]
else:
sys.exit("File does not exist")
else:
sys.exit("File is not a python(.py) file")
else:
sys.exit("Too few or many command-line arguments")
return filename
def count_loc(filename:str)->int:
counter = 0
with open(filename) as file:
for row in file:
if row[0].lstrip() != '#' and not row.isspace():
counter += 1
return counter
if __name__ == '__main__':
main()
Based on this I wrote a test file using PyTest as following:
from lines import is_input_valid, count_loc
import pytest
def test_input():
with pytest.raises(SystemExit, match = "Too few or many command-line arguments"):
is_input_valid("filename foo.bar lang.py")
is_input_valid("filename")
def test_file_name():
with pytest.raises(SystemExit, match = "File is not a python(.py) file"):
is_input_valid("filename foo.bar")
is_input_valid("filename file.txt")
def test_file_exists():
with pytest.raises(SystemExit) as e:
is_input_valid("filename abdcgr.py")
assert e.value == "File does not exist"
def test_count_loc():
assert count_loc("fuel.py") == 20
After trying to debug, it looks like the PyTest functions just jump to the final else statement in the is_input_valid function regardless of what input I give in there and so only the first test function passes with "Too few or many command-line arguments". All other test_input functions fail. I ran the source cod with the same input and it works exactly as expected. I don't know what is going wrong with the PyTest functions and why they aren't able to catch other exit exceptions.
I tried the same inputs as command line arguments when running the source code and the outputs are exactly as expected.
But when PyTest functions are being executed, it always jumps to the final else statement within the is_valid_input function and catches the same exit exception regardless of the input to that function.
Your test cases are wrong. The argument to is_input_valid()
is supposed to be a list of strings -- the first string is the script name, the second is the name of the file to check. You're just passing a single string, the whole command line.
You can use split()
to split it up into a list.
def test_input():
with pytest.raises(SystemExit, match = "Too few or many command-line arguments"):
is_input_valid("filename foo.bar lang.py".split())
is_input_valid("filename".split())
def test_file_name():
with pytest.raises(SystemExit, match = "File is not a python(.py) file"):
is_input_valid("filename foo.bar".split())
is_input_valid("filename file.txt".split())
def test_file_exists():
with pytest.raises(SystemExit) as e:
is_input_valid("filename abdcgr.py".split())
assert e.value == "File does not exist"