pytest Exceptions - Part II
Tags: python, test, pytest, exception
Published: 2021-10-11 12:00:03

---
title: pytest Exceptions - Part II
published: true
date: 2021-06-10 00:00:00 UTC
tags: python, test, pytest, exception
canonical_url: https://tech.serhatteker.com/post/2021-06/pytest-exceptions-p2/
---

We've already seen how to test *exceptions* with pytest in [part I].  However what's going to happen if we didn't fully implement our method yet or don't want to test on different os platforms, language versions etc.?

For these kind of tests we can use `skip` and `xfail`:

- A **skip** means that you expect your test to pass only if some conditions are met,
- An **xfail** means that you expect a test to fail for some reason.

Let's assume we got a dummy method which calls a third party API;

```python
# utils.py
from typing import Optional

import requests

from .exceptions import ParametersError, PaymentGatewayError, UserPermissionError


def incomplete_business_logic_method(*args, **kwargs) -> Optional[str]:
    response = None
    try:
        response = expensive_calculation_method(*args, **kwargs)
    except APIGatewayError as exc:
        raise APIGatewayError() from exc
    except requests.exceptions.HTTPError as exc:
        if exc.response.status_code == 400:
            error = exc.response.json()
            code = error['code']
            message = error['message']

            if exc.code == 2001:
                raise ParametersError(exc.code, exc.message) from exc
            else:
                raise UserPermissionError(exc.code, exc.message) from exc

    return response
```

And **exceptions** module looks like this:

```python
# exceptions.py
class APIGatewayError(Exception):
    pass


class PaymentGatewayError(APIGatewayError):
    def __init__(self, code, message):
        self.code = code
        self.message = message


class ParametersError(PaymentGatewayError):
    pass


class UserPermissionError(PaymentGatewayError):
    pass
```


## xfail

You can use `xfail` marker to indicate that you expect a test to fail:

```python
# tests/test_utils.py
import pytest

from .exceptions import APIGatewayError


@pytest.mark.xfail(raises=APIGatewayError)
def test_incomplete_business_logic_method(self):
    ...
    return incomplete_business_logic_method(*args, **kwargs)
```

If a test is only expected to fail under a certain condition — like in `skipif`,
you can pass that condition as the first parameter:

```python
# tests/test_utils.py
import pytest


@pytest.mark.xfail(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_incomplete_business_logic_method(self):
    ...
    return incomplete_business_logic_method(*args, **kwargs)
```


## skip

The simplest way to skip a test function is to mark it with the `skip` *decorator* which may be passed an optional reason:

```python
# tests/test_utils.py
import pytest


@pytest.mark.skip(reason="not implement this yet")
def test_incomplete_business_logic_method(self):
    ...
    return incomplete_business_logic_method(*args, **kwargs)
```

### skipif

If you wish to skip something conditionally then you can use `skipif`:

```python
# tests/test_utils.py
import pytest


@pytest.mark.skiWe’ve already seen how to test exceptions with pytest in part I. However what’s going to happen if we didn’t fully implement our method yet or don’t want to test on different os platforms, language versions etc.? For these kind of tests we can use skip and xfail: A skip means that you expect your test to pass only if some conditions are met, An xfail means that you expect a test to fail for some reason.pif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_incomplete_business_logic_method(self):
    ...
    return incomplete_business_logic_method(*args, **kwargs)
```


## Addition

You can show extra info on *xfailed*  and *skipped* tests with `-rxs`:

```bash
$ pytest -rxs
```

Get more info on offical doc :[skip and xfail].



All done!




[part I]: https://tech.serhatteker.com/post/2019-08/pytest-exceptions-p1/
[skip and xfail]: https://docs.pytest.org/en/6.2.x/skipping.html#skip-and-xfail-dealing-with-tests-that-cannot-succeed