More work on the tests...

This commit is contained in:
Dave Jones
2016-04-05 09:45:44 +01:00
parent 2a2e77051d
commit 3acf8a0d3a
12 changed files with 397 additions and 28 deletions

148
tests/test_compat.py Normal file
View File

@@ -0,0 +1,148 @@
from __future__ import (
unicode_literals,
absolute_import,
print_function,
division,
)
str = type('')
import pytest
import random
from gpiozero.compat import *
# ported from the official test cases; see
# https://github.com/python/cpython/blob/master/Lib/test/test_math.py for original
NAN = float('nan')
INF = float('inf')
NINF = float('-inf')
def test_isclose_negative_tolerances():
with pytest.raises(ValueError):
isclose(1, 1, rel_tol=-1e-100)
with pytest.raises(ValueError):
isclose(1, 1, rel_tol=1e-100, abs_tol=-1e10)
def test_isclose_identical():
examples = [
(2.0, 2.0),
(0.1e200, 0.1e200),
(1.123e-300, 1.123e-300),
(12345, 12345.0),
(0.0, -0.0),
(345678, 345678),
]
for a, b in examples:
assert isclose(a, b, rel_tol=0.0, abs_tol=0.0)
def test_isclose_eight_decimals():
examples = [
(1e8, 1e8 + 1),
(-1e-8, -1.000000009e-8),
(1.12345678, 1.12345679),
]
for a, b in examples:
assert isclose(a, b, rel_tol=1e-8)
assert not isclose(a, b, rel_tol=1e-9)
def test_isclose_near_zero():
examples = [1e-9, -1e-9, -1e-150]
for a in examples:
assert not isclose(a, 0.0, rel_tol=0.9)
assert isclose(a, 0.0, abs_tol=1e-8)
def test_isclose_inf():
assert isclose(INF, INF)
assert isclose(INF, INF, abs_tol=0.0)
assert isclose(NINF, NINF)
assert isclose(NINF, NINF, abs_tol=0.0)
def test_isclose_inf_ninf_nan():
examples = [
(NAN, NAN),
(NAN, 1e-100),
(1e-100, NAN),
(INF, NAN),
(NAN, INF),
(INF, NINF),
(INF, 1.0),
(1.0, INF),
(INF, 1e308),
(1e308, INF),
]
for a, b in examples:
assert not isclose(a, b, abs_tol=0.999999999999999)
def test_isclose_zero_tolerance():
examples = [
(1.0, 1.0),
(-3.4, -3.4),
(-1e-300, -1e-300),
]
for a, b in examples:
assert isclose(a, b, rel_tol=0.0)
examples = [
(1.0, 1.000000000000001),
(0.99999999999999, 1.0),
(1.0e200, .999999999999999e200),
]
for a, b in examples:
assert not isclose(a, b, rel_tol=0.0)
def test_isclose_assymetry():
assert isclose(9, 10, rel_tol=0.1)
assert isclose(10, 9, rel_tol=0.1)
def test_isclose_integers():
examples = [
(100000001, 100000000),
(123456789, 123456788),
]
for a, b in examples:
assert isclose(a, b, rel_tol=1e-8)
assert not isclose(a, b, rel_tol=1e-9)
# ported from the official test cases; see
# https://github.com/python/cpython/blob/master/Lib/test/test_statistics.py for
# original
def test_mean():
examples = [
(4.8125, (0, 1, 2, 3, 3, 3, 4, 5, 5, 6, 7, 7, 7, 7, 8, 9)),
(22.015625, (17.25, 19.75, 20.0, 21.5, 21.75, 23.25, 25.125, 27.5)),
(INF, (1, 3, 5, 7, 9, INF)),
(NINF, (1, 3, 5, 7, 9, NINF)),
]
for result, values in examples:
values = list(values)
random.shuffle(values)
assert mean(values) == result
def test_mean_big_data():
c = 1e9
data = [3.4, 4.5, 4.9, 6.7, 6.8, 7.2, 8.0, 8.1, 9.4]
expected = mean(data) + c
assert expected != c
assert mean([x + c for x in data]) == expected
def test_mean_doubled_data():
data = [random.uniform(-3, 5) for _ in range(1000)]
expected = mean(data)
actual = mean(data * 2)
assert isclose(expected, actual)
def test_mean_empty():
with pytest.raises(ValueError):
mean(())
def test_median():
assert median([1, 2, 3, 4, 5, 6]) == 3.5
assert median([1, 2, 3, 4, 5, 6, 9]) == 4
def test_median_empty():
with pytest.raises(ValueError):
median(())

View File

@@ -68,3 +68,60 @@ def test_device_repr_after_close():
device.close()
assert repr(device) == '<gpiozero.GPIODevice object closed>'
def test_device_unknown_attr():
pin = MockPin(2)
device = GPIODevice(pin)
with pytest.raises(AttributeError):
device.foo = 1
def test_device_context_manager():
pin = MockPin(2)
with GPIODevice(pin) as device:
assert not device.closed
assert device.closed
def test_composite_device_sequence():
device = CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
)
assert len(device) == 2
assert device[0].pin.number == 2
assert device[1].pin.number == 3
assert device.tuple._fields == ('_0', '_1')
def test_composite_device_values():
device = CompositeDevice(
InputDevice(MockPin(2)),
InputDevice(MockPin(3))
)
assert device.value == (0, 0)
assert not device.is_active
device[0].pin.drive_high()
assert device.value == (1, 0)
assert device.is_active
def test_composite_device_named():
device = CompositeDevice(
foo=InputDevice(MockPin(2)),
bar=InputDevice(MockPin(3)),
_order=('foo', 'bar')
)
assert device.tuple._fields == ('foo', 'bar')
assert device.value == (0, 0)
assert not device.is_active
def test_composite_device_bad_init():
with pytest.raises(ValueError):
CompositeDevice(foo=1, bar=2, _order=('foo',))
with pytest.raises(ValueError):
CompositeDevice(close=1)
def test_composite_device_read_only():
device = CompositeDevice(
foo=InputDevice(MockPin(2)),
bar=InputDevice(MockPin(3))
)
with pytest.raises(AttributeError):
device.foo = 1

View File

@@ -7,11 +7,16 @@ from __future__ import (
str = type('')
import sys
import pytest
import mock
from threading import Event
from gpiozero.pins.mock import MockPin, MockPulledUpPin, MockChargingPin
from gpiozero.pins.mock import (
MockPin,
MockPulledUpPin,
MockChargingPin,
MockTriggerPin,
)
from gpiozero import *
@@ -136,12 +141,43 @@ def test_input_motion_sensor():
assert sensor.wait_for_no_motion(1)
assert not sensor.motion_detected
@pytest.mark.skipif(True, reason='Freezes')
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_input_light_sensor():
pin = MockChargingPin(2)
sensor = LightSensor(pin)
pin.charge_time = 1
assert not sensor.light_detected
pin.charge_time = 0
assert sensor.light_detected
pin.charge_time = 0.1
assert sensor.wait_for_dark(1)
pin.charge_time = 0.0
assert sensor.wait_for_light(1)
@pytest.mark.skipif(hasattr(sys, 'pypy_version_info'),
reason='timing is too random on pypy')
def test_input_distance_sensor():
echo_pin = MockPin(2)
trig_pin = MockTriggerPin(3)
trig_pin.echo_pin = echo_pin
trig_pin.echo_time = 0.02
with pytest.raises(ValueError):
DistanceSensor(echo_pin, trig_pin, max_distance=-1)
# normal queue len is large (because the sensor is *really* jittery) but
# we want quick tests and we've got precisely controlled pins :)
sensor = DistanceSensor(echo_pin, trig_pin, queue_len=5, max_distance=1)
assert sensor.max_distance == 1
assert sensor.trigger is trig_pin
assert sensor.echo is echo_pin
assert sensor.wait_for_out_of_range(1)
assert not sensor.in_range
assert sensor.distance == 1.0 # should be waay before max-distance so this should work
trig_pin.echo_time = 0.0
assert sensor.wait_for_in_range(1)
assert sensor.in_range
assert sensor.distance < sensor.threshold_distance # depending on speed of machine, may not reach 0 here
sensor.threshold_distance = 0.1
assert sensor.threshold_distance == 0.1
with pytest.raises(ValueError):
sensor.max_distance = -1
sensor.max_distance = 20
assert sensor.max_distance == 20
assert sensor.threshold_distance == 0.1

View File

@@ -0,0 +1,88 @@
from __future__ import (
unicode_literals,
absolute_import,
print_function,
division,
)
str = type('')
import pytest
from math import sin, cos, radians
from time import time
from gpiozero import *
try:
from math import isclose
except ImportError:
from gpiozero.compat import isclose
def test_negated():
assert list(negated(())) == []
assert list(negated((True, True, False, False))) == [False, False, True, True]
def test_inverted():
assert list(inverted(())) == []
assert list(inverted((1, 0, 0.1, 0.5))) == [0, 1, 0.9, 0.5]
def test_scaled():
assert list(scaled((0, 1, 0.5, 0.1), 0, 1)) == [0, 1, 0.5, 0.1]
assert list(scaled((0, 1, 0.5, 0.1), -1, 1)) == [-1, 1, 0.0, -0.8]
def test_clamped():
assert list(clamped((-1, 0, 1, 2))) == [0, 0, 1, 1]
def test_quantized():
assert list(quantized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 4)) == [
0.0, 0.0, 0.0, 0.25, 0.25, 0.5, 0.5, 0.5, 0.75, 0.75, 1.0]
assert list(quantized((0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 5)) == [
0.0, 0.0, 0.2, 0.2, 0.4, 0.4, 0.6, 0.6, 0.8, 0.8, 1.0]
def test_conjunction():
assert list(conjunction(())) == []
assert list(conjunction((False, True))) == [False, True]
assert list(conjunction((0, 1, 0, 1), (0, 0, 0, 1))) == [0, 0, 0, 1]
def test_disjunction():
assert list(disjunction(())) == []
assert list(disjunction((False, True))) == [False, True]
assert list(disjunction((0, 1, 0, 1), (0, 0, 0, 1))) == [0, 1, 0, 1]
def test_averaged():
assert list(averaged(())) == []
assert list(averaged((0, 0.5, 1), (1, 1, 1))) == [0.5, 0.75, 1]
def test_queued():
assert list(queued((1, 2, 3, 4, 5), 5)) == [1]
assert list(queued((1, 2, 3, 4, 5, 6), 5)) == [1, 2]
def test_pre_delayed():
start = time()
for v in pre_delayed((0, 0, 0), 0.01):
assert v == 0
assert time() - start >= 0.01
start = time()
def test_post_delayed():
start = time()
for v in post_delayed((1, 2, 2), 0.01):
if v == 1:
assert time() - start < 0.01
else:
assert time() - start >= 0.01
start = time()
assert time() - start >= 0.01
def test_random_values():
for i, v in zip(range(1000), random_values()):
assert 0 <= v <= 1
def test_sin_values():
for i, v in zip(range(1000), sin_values()):
assert isclose(v, sin(radians(i)), abs_tol=1e-9)
def test_cos_values():
for i, v in zip(range(1000), cos_values()):
assert isclose(v, cos(radians(i)), abs_tol=1e-9)