[Pytest-commit] Issue #475: Misleading pytest exception description (hpk42/pytest)

Jurko Gospodnetić issues-reply at bitbucket.org
Wed Mar 5 16:47:32 CET 2014


New issue 475: Misleading pytest exception description
https://bitbucket.org/hpk42/pytest/issue/475/misleading-pytest-exception-description

Jurko Gospodnetić:

Today, while mentoring a new colleague in Python and TDD, she ran into a pytest exception description which confused her, and with her being a novice programmer, was completely out of her league to debug.

Here is a reduced script demonstrating the issue:

```
InvalidLabSize = -1

class Lab:
    def __init__(self, size):
        if size <= 0:
            raise Exception(InvalidLabSize)

import pytest

def test_invalid_lab_size():
    with pytest.raises(InvalidLabSize):
        Lab(0)
```

The given test code has a bug - ```pytest.raises()``` should be given ```Exception``` class as its parameter and not an integer ```InvalidLabSize```. However, pytest
reports this in a most misleading way:

```
#!text
D:\Workplace>py3 -m pytest aaa.py
============================= test session starts =============================
platform win32 -- Python 3.3.3 -- py-1.4.20 -- pytest-2.5.2
collected 1 items

aaa.py F

================================== FAILURES ===================================
____________________________ test_invalid_lab_size ____________________________

    def test_invalid_lab_size():
        with pytest.raises(InvalidLabSize):
>           Lab(0)
E           TypeError: issubclass() arg 2 must be a class or tuple of classes

aaa.py:15: TypeError
========================== 1 failed in 0.05 seconds ===========================
```

First, it points to an incorrect code line - it points to the code line ```Lab(0)``` as causing the error when in fact it was the line before that caused it.
Second, it complains about some 'argument number 2' to some ```issubclass()``` call having to be a class or a tuple of classes, when neither the user code nor anything displayed in the given exception stack information contains any ```issubclass()``` calls.

It should in fact say that the first parameter to ```pyteset.raises()``` should be a class or a tuple of classes.

----

As a side-note, I tried rewriting the test using the older pytest.raises() calling style (without using a ```with``` context manager):

```
#!python
InvalidLabSize = -1

class Lab:
    def __init__(self, size):
        if size <= 0:
            raise Exception(InvalidLabSize)

import pytest

def test_invalid_lab_size():
    pytest.raises(InvalidLabSize, Lab, 0)
```

and this reports much more relevant information when run under Python 3.x:

```
D:\Workplace>py3 -m pytest aaa.py
============================= test session starts =============================
platform win32 -- Python 3.3.3 -- py-1.4.20 -- pytest-2.5.2
collected 1 items

aaa.py F

================================== FAILURES ===================================
____________________________ test_invalid_lab_size ____________________________

    def test_invalid_lab_size():
>       pytest.raises(InvalidLabSize, Lab, 0)
E       TypeError: catching classes that do not inherit from BaseException is not allowed

aaa.py:31: TypeError
========================== 1 failed in 0.04 seconds ===========================
```

Running it under Python 2.x on the other hand displays a bit less but still misleading information:

```
D:\Workplace>py2 -m pytest aaa.py
============================= test session starts =============================
platform win32 -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
collected 1 items

aaa.py F

================================== FAILURES ===================================
____________________________ test_invalid_lab_size ____________________________

    def test_invalid_lab_size():
>       pytest.raises(InvalidLabSize, Lab, 0)

aaa.py:31:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <aaa.Lab instance at 0x0000000003043B88>, size = 0

    def __init__(self, size):
        if size <= 0:
>           raise Exception(InvalidLabSize)
E           Exception: -1

aaa.py:24: Exception
========================== 1 failed in 0.12 seconds ===========================
```

It says that an Exception got raised when it should in fact say that an Exception got raised but an integer -1 was expected.

Hope this helps.

Best regards,
  Jurko Gospodnetić




More information about the pytest-commit mailing list