Home > Back-end >  Using Pytest to test a Python Program
Using Pytest to test a Python Program

Time:11-30

TI am quite new to Python Programming and have a question on testing using Pytest. In a high-level, I have a program that takes 3 pieces of user input and generates a text file in the end. For my tests, I want to basically compare the files my program outputted, with what it should be.

Now, I am not sure how to go about testing. The program itself takes no arguments, but just relies on 3 pieces of user input, which I'll use monkeypatch to simulate. Do I create a new python file called program_test.py and have methods in here that call the original program? I have tried this, but I'm having trouble actually calling the original program and sending in the simulated inputs. Or, do I have tests in the original program (which doesn't make much sense to me).

I want something like this:

import my_program

def test_1():
    inputs = iter(['input1', 'input2', 'input3'])
    monkeypatch.setattr('builtins.input', lambda x: next(inputs))
    my_program
    # now do some assertion with some file comparison
    # pseudocode
    assert filecompare.cmp(expectedfile, actualfile)

This just seems to be running the original program and I think its to do with the import statement i.e. it is never running test_1(), probably because I never call it? Any help would be appreciated!

CodePudding user response:

Without providing your my_program code it's hard to tell what's going on.

Since you are mentioning import problems, I guess your not defining main() and if __name__ == "__main__".

Here's a little example of how you can test that.

First, structure your my_program to have main function which contains the code and then add if __name__ == "__main__" which will allow you to run main function if the my_program is executed directly but also to import my_program as module to other files (without running it, for more information please see: What does if name == "main": do?).

my_program:

def main():
    x = input()
    y = input()
    z = input()
    with open("test", "w") as f_out:
        f_out.write(f"{x}-{y}-{z}")


if __name__ == "__main__":
    main()

Now you can create a test.py file and test the main function of my_program:

import os
import filecmp
import my_program


def test_success(monkeypatch):
    inputs = ["input1", "input2", "input3"]
    monkeypatch.setattr("builtins.input", lambda: next(iter(inputs)))
    my_program.main()
    with open("expected", "w") as f_out:
        f_out.write("-".join(inputs))
    assert filecmp.cmp("expected", "test")
    os.remove("test")
    os.remove("expected")


def test_fail(monkeypatch):
    inputs = ["input1", "input2", "input3"]
    monkeypatch.setattr("builtins.input", lambda: next(iter(inputs)))
    my_program.main()
    with open("expected", "w") as f_out:
        f_out.write("something-else-test")
    assert not filecmp.cmp("expected", "test")
    os.remove("test")
    os.remove("expected")

This is an example so I used os.remove to delete the files. Ideally you would define fixtures in your tests to use tempfile and generate random temporary files which will be automatically deleted after your tests.

  • Related