Skip to content

Commit

Permalink
test: Improve test coverage (#106)
Browse files Browse the repository at this point in the history
* test(CostMl, CostCosine): Add test, delete duplicate functions, set random seed

* refactor(pw_constant): inject seed for reproducible random state

* test(test_costs): set random seed

* test(test_costs): running black

* test(costlinear): fix an import mishandled by merge with master
  • Loading branch information
oboulant authored Jan 12, 2021
1 parent 6a65928 commit a9d1827
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 78 deletions.
8 changes: 6 additions & 2 deletions src/ruptures/datasets/pw_constant.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
"""Piecewise constant signal (with noise)"""

import numpy as np
from numpy import random as rd
from numpy.random import RandomState

from ruptures.utils import draw_bkps


def pw_constant(n_samples=200, n_features=1, n_bkps=3, noise_std=None, delta=(1, 10)):
def pw_constant(
n_samples=200, n_features=1, n_bkps=3, noise_std=None, delta=(1, 10), seed=None
):
"""Return a piecewise constant signal and the associated changepoints.
Args:
Expand All @@ -15,6 +17,7 @@ def pw_constant(n_samples=200, n_features=1, n_bkps=3, noise_std=None, delta=(1,
n_bkps (int, optional): number of changepoints
noise_std (float, optional): noise std. If None, no noise is added
delta (tuple, optional): (delta_min, delta_max) max and min jump values
seed (int): random seed
Returns:
tuple: signal of shape (n_samples, n_features), list of breakpoints
Expand All @@ -27,6 +30,7 @@ def pw_constant(n_samples=200, n_features=1, n_bkps=3, noise_std=None, delta=(1,
delta_min, delta_max = delta
# mean value
center = np.zeros(n_features)
rd = RandomState(seed)
for ind in np.split(tt_, bkps):
if ind.size > 0:
# jump value
Expand Down
117 changes: 41 additions & 76 deletions tests/test_costs.py
Original file line number Diff line number Diff line change
@@ -1,101 +1,50 @@
import pytest
from ruptures.costs import (
CostAR,
CostCLinear,
CostLinear,
CostL1,
CostL2,
CostLinear,
CostNormal,
CostRank,
CostRbf,
cost_factory,
)
import numpy as np
from ruptures.costs import cost_factory, CostLinear
from ruptures.datasets import pw_constant
from ruptures.exceptions import NotEnoughPoints
import numpy as np


@pytest.fixture(scope="module")
def signal_bkps_1D():
signal, bkps = pw_constant(n_features=1)
signal, bkps = pw_constant(n_features=1, seed=1234567890)
return signal, bkps


@pytest.fixture(scope="module")
def signal_bkps_1D_noisy():
signal, bkps = pw_constant(n_features=1, noise_std=1)
signal, bkps = pw_constant(n_features=1, noise_std=1, seed=1234567890)
return signal, bkps


@pytest.fixture(scope="module")
def signal_bkps_5D():
signal, bkps = pw_constant(n_features=5)
signal, bkps = pw_constant(n_features=5, seed=1234567890)
return signal, bkps


@pytest.fixture(scope="module")
def signal_bkps_5D_noisy():
signal, bkps = pw_constant(n_features=5, noise_std=1)
signal, bkps = pw_constant(n_features=5, noise_std=1, seed=1234567890)
return signal, bkps


cost_classes = {CostAR, CostL1, CostL2, CostNormal, CostRbf, CostRank, CostCLinear}
cost_names = {"ar", "l1", "l2", "normal", "rbf", "rank", "clinear"}


@pytest.mark.parametrize("cost", cost_classes)
def test_costs_1D(signal_bkps_1D, cost):
signal, bkps = signal_bkps_1D
cost.fit(signal)
cost.fit(signal.flatten())
cost.error(0, 100)
cost.error(100, signal.shape[0])
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)


@pytest.mark.parametrize("cost", cost_classes)
def test_costs_1D_noisy(signal_bkps_1D_noisy, cost):
signal, bkps = signal_bkps_1D_noisy
cost.fit(signal)
cost.fit(signal.flatten())
cost.error(0, 100)
cost.error(100, signal.shape[0])
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)


@pytest.mark.parametrize("cost", cost_classes)
def test_costs_5D(signal_bkps_5D, cost):
signal, bkps = signal_bkps_5D
cost.fit(signal)
cost.error(0, 100)
cost.error(100, signal.shape[0])
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)


@pytest.mark.parametrize("cost", cost_classes)
def test_costs_5D_noisy(signal_bkps_5D_noisy, cost):
signal, bkps = signal_bkps_5D_noisy
cost.fit(signal)
cost.error(0, 100)
cost.error(100, signal.shape[0])
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)
cost_names = {
"ar",
"l1",
"l2",
"normal",
"rbf",
"rank",
"clinear",
"mahalanobis",
"cosine",
}


@pytest.mark.parametrize("cost_name", cost_names)
def test_costs_1D(signal_bkps_1D, cost_name):
def test_costs_1D_names(signal_bkps_1D, cost_name):
signal, bkps = signal_bkps_1D
cost = cost_factory(cost_name)
cost.fit(signal)
Expand All @@ -105,11 +54,15 @@ def test_costs_1D(signal_bkps_1D, cost_name):
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)
if cost_name == "cosine":
cost.min_size = 4
cost.error(1, 2)
else:
cost.error(1, 2)


@pytest.mark.parametrize("cost_name", cost_names)
def test_costs_1D_noisy(signal_bkps_1D_noisy, cost_name):
def test_costs_1D_noisy_names(signal_bkps_1D_noisy, cost_name):
signal, bkps = signal_bkps_1D_noisy
cost = cost_factory(cost_name)
cost.fit(signal)
Expand All @@ -119,11 +72,15 @@ def test_costs_1D_noisy(signal_bkps_1D_noisy, cost_name):
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)
if cost_name == "cosine":
cost.min_size = 4
cost.error(1, 2)
else:
cost.error(1, 2)


@pytest.mark.parametrize("cost_name", cost_names)
def test_costs_5D(signal_bkps_5D, cost_name):
def test_costs_5D_names(signal_bkps_5D, cost_name):
signal, bkps = signal_bkps_5D
cost = cost_factory(cost_name)
cost.fit(signal)
Expand All @@ -132,11 +89,15 @@ def test_costs_5D(signal_bkps_5D, cost_name):
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)
if cost_name == "cosine":
cost.min_size = 4
cost.error(1, 2)
else:
cost.error(1, 2)


@pytest.mark.parametrize("cost_name", cost_names)
def test_costs_5D_noisy(signal_bkps_5D_noisy, cost_name):
def test_costs_5D_noisy_names(signal_bkps_5D_noisy, cost_name):
signal, bkps = signal_bkps_5D_noisy
cost = cost_factory(cost_name)
cost.fit(signal)
Expand All @@ -145,7 +106,11 @@ def test_costs_5D_noisy(signal_bkps_5D_noisy, cost_name):
cost.error(10, 50)
cost.sum_of_costs(bkps)
with pytest.raises(NotEnoughPoints):
cost.error(1, 2)
if cost_name == "cosine":
cost.min_size = 4
cost.error(1, 2)
else:
cost.error(1, 2)


def test_factory_exception():
Expand Down

0 comments on commit a9d1827

Please sign in to comment.