# Common Patterns for Tests¶

In this section you will learn some useful features of pytest that can make your tests succinct and easy to maintain.

## Parametrized Tests¶

Tests that apply the same general test logic to a collection of different parameters can use parametrized tests. For example, this:

```
import numpy as np
from ..refraction import snell
def test_perpendicular():
# For any indexes, a ray normal to the surface should not bend.
# We'll try a couple different combinations of indexes....
actual = snell(0, 2.00, 3.00)
expected = 0
assert actual == expected
actual = snell(0, 3.00, 2.00)
expected = 0
assert actual == expected
```

can be rewritten as:

```
import numpy as np
import pytest
from ..refraction import snell
@pytest.mark.parametrize('n1, n2',
[(2.00, 3.00),
(3.00, 2.00),
])
def test_perpendicular(n1, n2):
# For any indexes, a ray normal to the surface should not bend.
# We'll try a couple different combinations of indexes....
actual = snell(0, n1, n2)
expected = 0
assert actual == expected
```

The string `'n1, n2'`

specifies which parameters this decorator will fill in.
Pytest will run `test_perpendicular`

twice, one for each entry in the
list `[(2.00, 3.00), (3.00, 2.00)]`

, passing in the respective values `n1`

and `n2`

as arguments.

From here we refer you to the pytest parametrize documentation.

## Fixtures¶

Tests that have different logic but share the same setup code can use pytest fixtures. For example, this:

```
import numpy as np
def test_height():
# Construct a 1-dimensional Gaussian peak.
x = np.linspace(-10, 10, num=21)
sigma = 3.0
peak = np.exp(-(x / sigma)**2 / 2) / (sigma * np.sqrt(2 * np.pi))
expected = 1 / (sigma * np.sqrt(2 * np.pi))
# Test that the peak height is correct.
actual = np.max(peak)
assert np.allclose(actual, expected)
def test_nonnegative():
# Construct a 1-dimensional Gaussian peak.
x = np.linspace(-10, 10, num=20)
sigma = 3.0
peak = np.exp(-(x / sigma)**2 / 2) / (sigma * np.sqrt(2 * np.pi))
# Test that there are no negative values.
assert np.all(peak >= 0)
```

can be written as:

```
import pytest
import numpy as np
@pytest.fixture
def peak():
# Construct a 1-dimensional Gaussian peak.
x = np.linspace(-10, 10, num=21)
sigma = 3.0
peak = np.exp(-(x / sigma)**2 / 2) / (sigma * np.sqrt(2 * np.pi))
return peak
def test_height(peak):
expected = 1 / (sigma * np.sqrt(2 * np.pi))
# Test that the peak height is correct.
actual = np.max(peak)
assert np.allclose(actual, expected)
def test_nonnegative(peak):
# Test that there are no negative values.
assert np.all(peak >= 0)
```

To reuse a fixture in multiple files, add it to `conftest.py`

located in the
`tests/`

directory. It will automatically be imported by pytest into each
test module.

From here we refer you to the pytest fixtures documentation.

## Skipping Tests¶

Sometimes it is useful to skip specific tests under certain conditions. Examples:

```
import pytest
import sys
@pytest.mark.skipif(sys.version_info < (3, 7),
reason="requires python3.7 or higher")
def test_something():
...
@pytest.mark.skipif(sys.platform == 'win32',
reason="does not run on windows")
def test_something_that_does_not_work_on_windows():
...
def test_something_that_needs_a_special_dependency():
some_library = pytest.importorskip("some_library")
...
```

From here we refer you to the pytest skipping documentation.