Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get started with testing on an existing python script?

I'm fairly experienced with python as a tool for datascience, no CS background (but eager to learn).

I've inherited a 3K line python script (simulates thermal effects on a part of a machine). It was built organically by physics people used to matlab. I've cleaned it up and modularized it (put it into a class and functions). Now I want an easy way to be certain it's working correctly after someone updates it. There have been some frustrating debugging sessions lately. I figure testing of some form can help there.

My question is how do I even get started in this case of a large existing script? I see pytest and unittest but is that where I should start? The code is roughly structured like this:

class Simulator:
    parameters = input_file
    def __init__(self):
        self.fn1
        self.fn2
        self.fn3

    def fn1():
        # with nested functions
    def fn2
    def fn3
    ...
    def fn(n)

Each function either generates or acts on some data. Would a way to test to have some standardized input/output run and check against that? Is there a way to do this within the standard convention of testing?

Appreciate any advice or tips, cheers!

like image 542
Declan Avatar asked Jul 30 '26 23:07

Declan


1 Answers

Broadly speaking, you test a function by calling it with arguments and checking if the return value is what you expect it to be. This means you should know beforehand how you expect your function to behave.

Here's a test for a simple add function:

def add(a, b):
    return a + b

def test_add_function():
    a = 1
    b = 2
    assert add(a, b) == 3  # we KNOW that adding 1 + 2 must equal 3

If you call test_add_function and no AssertionError is raised, congrats! Your test passed.

Of course, testing gets messier if you don't have "pure" functions, but rather objects that operate on shared data, like classes. Still, the logic is basically the same: call the function and check whether the expected result actually happens:

class MyClass:
    def __init__(self, a):
        self.a = a

    def add_one_to_a(self):
        self.a += 1


def test_method_add_one_to_a():
    initial_a = 1
    instance = MyClass(a=1)
    assert instance.a == initial_a  # we expect this to be 1
    instance.add_one_to_a()  # instance.a is now 2
    assert instance.a == initial_a + 1  # we expect this to be 2

I suggest reading/watching some tutorials on Python's unittest module to get your feet wet, especially getting used to the unittest.TestCase class, which helps a lot to common test operations, like set up/tear down routines (which allows you to e.g. "refresh" your Simulator instance between tests), testing if an error is raised when a function is called with wrong arguments, etc.

There are of course other strategies when things are more complicated than this (as they often are), like mocking objects which basically allows you to inspect any object/function called or modified by another object/function, check if it was called, what arguments were used, and so on.

If testing your functions is still too complex, this probably means that your code isn't modularized enough, or that your functions try to perform too many things at once.

like image 125
jfaccioni Avatar answered Aug 02 '26 13:08

jfaccioni