1

In a method that looks like:

def my_method(p):
    if p == 5:
        return
    elif p == 6:
        do_something()
        return
    else:
        do_something_different()
        return

How do I use Python unit test to check that when I call my_method(5) nothing extra is executed or changed outside my_method? I know that I can mock do_something and do_something_different and use assert_not_called but, is there a way to do it that only considers the if p == 5: part?

Katu
  • 1,296
  • 1
  • 24
  • 38
  • 2
    How could you ever tell without checking all memory that the method could potentially affect? If you're testing it as a black box, you can't. If you have a white box, use your common sense. – Mad Physicist Jan 20 '22 at 15:53
  • If you restrict the question to something more sensible, like `do*()` all affect some limited portion of the state, you can verify that that portion does not change. But "no side effects at all" is a tall order to prove satisfactorily. – Mad Physicist Jan 20 '22 at 15:55
  • Any chance that you actually want to test if _everything_ got executed? In that case take a look at [`coverage`](https://coverage.readthedocs.io/en/6.2/). In any case: With code-coverage you'll see what wasn't executed. – Stefan Falk Jan 20 '22 at 15:55
  • 1
    There's a joke in the Haskell community that a function that returns an `IO` value could do anything, including launch nuclear missiles. Here you have a function which is called only for its side effect; there are too many things that `my_method` could leave undone to check for all of them. – chepner Jan 20 '22 at 16:25
  • Related question: https://stackoverflow.com/questions/55422951/unit-testing-a-method-that-update-only-some-properties – Dirk Herrmann Jan 20 '22 at 16:34

1 Answers1

1

"nothing extra is executed .."

Using coverage you can see what has been executed and therefore also see what has not been executed.

You'll get a report and see what your tests didn't cover. For example:

$ coverage report -m
Name                      Stmts   Miss  Cover   Missing
-------------------------------------------------------
my_program.py                20      4    80%   33-35, 39
my_other_module.py           56      6    89%   17-23
-------------------------------------------------------
TOTAL                        76     10    87%

It also supports the generation of HTML files so you get a visualization too if needed. In the docs find this example.

If you run my_method(5), coverage will therefore show you what parts of your program weren't executed.

".. or changed outside my_method"

I have never done something like this and I am not sure if it's possible in a sensible way but I found this question which refers to tracemalloc. Maybe this module can help you.

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378