Skip to content

Commit

Permalink
fixing tests: moved all pyrates imports into test functions and added…
Browse files Browse the repository at this point in the history
… fixture that preserves working directory before/after a given test.
  • Loading branch information
dafrose committed Apr 19, 2020
1 parent a032bec commit 494b3e8
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 82 deletions.
15 changes: 15 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Pytest module-wide configuration file."""

import pytest

@pytest.fixture(autouse=True)
def run_around_tests():
# Code that will run before your test
# Find and save current (test) working directory
import os
cwd = os.getcwd()
# A test function will be run at this point
yield
# Code that will run after the test
# revert changes to working directory
os.chdir(cwd)
122 changes: 70 additions & 52 deletions tests/test_backend_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,8 @@

# external imports
import numpy as np
import tensorflow as tf
import pytest

# pyrates internal imports
from pyrates.backend.parser import parse_equations, parse_dict
from pyrates.backend.parser import ExpressionParser
from pyrates.backend.numpy_backend import NumpyBackend
from pyrates.backend.tensorflow_backend import TensorflowBackend

# meta infos
__author__ = "Richard Gast, Daniel Rose"
__status__ = "Development"
Expand All @@ -33,6 +26,7 @@ def setup_module():
# Tests #
#########


def test_1_1_expression_parser_init():
"""Testing initializations of different expression parsers:
Expand All @@ -43,7 +37,10 @@ def test_1_1_expression_parser_init():
"""

# list parsers to be tested and their backends
from pyrates.backend import ExpressionParser
parsers = [ExpressionParser, ExpressionParser]
from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend.numpy_backend import NumpyBackend
backends = [TensorflowBackend, NumpyBackend]

# test minimal minimal call example
Expand All @@ -64,21 +61,24 @@ def test_1_2_expression_parser_parsing_exceptions():
"""

# list parsers to be tested
from pyrates.backend import ExpressionParser
parsers = [ExpressionParser, ExpressionParser]
from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend.numpy_backend import NumpyBackend
backends = [TensorflowBackend, NumpyBackend]

# test expected exceptions
##########################

for Parser, backend in zip(parsers, backends):

b = backend()

# undefined variables
with pytest.raises(ValueError):
Parser("a + b", {}, backend=b).parse_expr()

# wrong dimensionality of dictionary arguments
from pyrates.backend import parse_dict
args = parse_dict({'a': {'vtype': 'constant', 'value': np.ones((3, 3)), 'dtype': 'float32', 'shape': (3, 3)},
'b': {'vtype': 'constant', 'value': np.ones((4, 4)), 'dtype': 'float32', 'shape': (4, 4)}},
backend=b)
Expand Down Expand Up @@ -117,28 +117,30 @@ def test_1_3_expression_parser_math_ops():
"""

# define test cases
math_expressions = [("4 + 5", 9.), # simple addition
("4 - 5", -1.), # simple subtraction
("4. * 5.", 20.), # simple multiplication
("4. / 5.", 0.8), # simple division
("4.^2.", 16.), # simple exponentiation
("4. + -5.", -1.), # negation of variable
("4. * -2.", -8.), # negation of variable in higher-order operation
("4. + 5. * 2.", 14.), # multiplication before addition
("(4. + 5.) * 2.", 18.), # parentheses before everything
("4. * 5.^2.", 100.) # exponentiation before multiplication
math_expressions = [("4 + 5", 9.), # simple addition
("4 - 5", -1.), # simple subtraction
("4. * 5.", 20.), # simple multiplication
("4. / 5.", 0.8), # simple division
("4.^2.", 16.), # simple exponentiation
("4. + -5.", -1.), # negation of variable
("4. * -2.", -8.), # negation of variable in higher-order operation
("4. + 5. * 2.", 14.), # multiplication before addition
("(4. + 5.) * 2.", 18.), # parentheses before everything
("4. * 5.^2.", 100.) # exponentiation before multiplication
]

# test expression parser on expression results using tensorflow backend
#######################################################################

# define backend
from pyrates.backend.tensorflow_backend import TensorflowBackend
b = TensorflowBackend()

# evaluate expressions
for expr, target in math_expressions:

# tensorflow-based parser
from pyrates.backend import ExpressionParser
p = ExpressionParser(expr_str=expr, args={}, backend=b)
p.parse_expr()
result = p.rhs
Expand All @@ -154,6 +156,7 @@ def test_1_3_expression_parser_math_ops():
##################################################################

# define backend
from pyrates.backend.numpy_backend import NumpyBackend
b = NumpyBackend()

# evaluate expressions
Expand All @@ -179,21 +182,25 @@ def test_1_4_expression_parser_logic_ops():
:class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
"""

from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend import ExpressionParser

# define test cases
logic_expressions = ["4 == 4", # simple equals
"4 != 5", # simple not-equals
"4 < 5", # simple less
"5 > 4", # simple larger
"4 <= 4", # less equals I
"4 <= 5", # less equals II
"5 >= 5", # larger equals I
"5 >= 4", # larger equals II
logic_expressions = ["4 == 4", # simple equals
"4 != 5", # simple not-equals
"4 < 5", # simple less
"5 > 4", # simple larger
"4 <= 4", # less equals I
"4 <= 5", # less equals II
"5 >= 5", # larger equals I
"5 >= 4", # larger equals II
]

# test expression parsers on expression results with tensforflow backend
########################################################################

# define backend

b = TensorflowBackend()

# correct expressions
Expand Down Expand Up @@ -228,11 +235,11 @@ def test_1_4_expression_parser_logic_ops():
##################################################################

# define backend
from pyrates.backend.numpy_backend import NumpyBackend
b = NumpyBackend()

# correct expressions
for expr in logic_expressions:

# numpy-based parser
p = ExpressionParser(expr_str=expr, args={}, backend=b)
p.parse_expr()
Expand Down Expand Up @@ -266,6 +273,11 @@ def test_1_5_expression_parser_indexing():
:class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
"""

from pyrates.backend import ExpressionParser
from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend.numpy_backend import NumpyBackend
from pyrates.backend import parse_dict

# test indexing ability of tensorflow-based parser
##################################################

Expand All @@ -276,16 +288,16 @@ def test_1_5_expression_parser_indexing():
'd': {'vtype': 'constant', 'value': 4, 'Shape': (), 'dtype': 'int32'}}

# define valid test cases
indexed_expressions = [("A[:]", A[:]), # single-dim indexing I
("A[0]", A[0]), # single-dim indexing II
("A[-2]", A[-2]), # single-dim indexing III
("A[0:5]", A[0:5]), # single-dim slicing I
("A[-1:0:-1]", A[-1:0:-1]), # single-dim slicing II
("A[4,5]", A[4, 5]), # two-dim indexing I
("A[5,0:-2]", A[5, 0:-2]), # two-dim indexing II
("A[A > 0.]", A[A > 0.]), # boolean indexing
("A[B]", A[B]), # indexing with other array
("A[d:8 - 1]", # using variables as indices
indexed_expressions = [("A[:]", A[:]), # single-dim indexing I
("A[0]", A[0]), # single-dim indexing II
("A[-2]", A[-2]), # single-dim indexing III
("A[0:5]", A[0:5]), # single-dim slicing I
("A[-1:0:-1]", A[-1:0:-1]), # single-dim slicing II
("A[4,5]", A[4, 5]), # two-dim indexing I
("A[5,0:-2]", A[5, 0:-2]), # two-dim indexing II
("A[A > 0.]", A[A > 0.]), # boolean indexing
("A[B]", A[B]), # indexing with other array
("A[d:8 - 1]", # using variables as indices
A[4:8 - 1]),
]

Expand All @@ -309,16 +321,15 @@ def test_1_5_expression_parser_indexing():
assert result == pytest.approx(target, rel=1e-6)

# define invalid test cases
indexed_expressions_wrong = ["A[1.2]", # indexing with float variables
"A[all]", # indexing with undefined key words
"A[-11]", # index out of bounds
"A[0:5:2:1]", # too many arguments for slicing
indexed_expressions_wrong = ["A[1.2]", # indexing with float variables
"A[all]", # indexing with undefined key words
"A[-11]", # index out of bounds
"A[0:5:2:1]", # too many arguments for slicing
"A[-1::0:-1]", # wrong slicing syntax II
]

# test expression parsers on expression results
for expr in indexed_expressions_wrong:

# define backend
b = TensorflowBackend()
args = parse_dict(arg_dict, backend=b)
Expand Down Expand Up @@ -363,6 +374,11 @@ def test_1_6_expression_parser_funcs():
:class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
"""

from pyrates.backend import ExpressionParser
from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend.numpy_backend import NumpyBackend
from pyrates.backend import parse_dict

# define variables
A = np.array(np.random.randn(10, 10), dtype=np.float32)

Expand All @@ -378,9 +394,9 @@ def test_1_6_expression_parser_funcs():
]

# define invalid test cases
expressions_wrong = ["abs((4.)", # wrong parentheses I
"abs[4.]", # wrong parentheses II
"abs(0. True)", # no comma separation on arguments
expressions_wrong = ["abs((4.)", # wrong parentheses I
"abs[4.]", # wrong parentheses II
"abs(0. True)", # no comma separation on arguments
"abs(0.,1,5,3)", # wrong argument number
]

Expand Down Expand Up @@ -408,7 +424,6 @@ def test_1_6_expression_parser_funcs():

# invalid cases
for expr in expressions_wrong:

# define backend
b = TensorflowBackend()
args = parse_dict({'A': {'vtype': 'constant', 'value': A, 'shape': A.shape, 'dtype': A.dtype}}, backend=b)
Expand Down Expand Up @@ -451,9 +466,14 @@ def test_1_7_equation_parsing():
:func:`parse_equation`: Detailed documentation of parse_equation arguments.
"""

from pyrates.backend.tensorflow_backend import TensorflowBackend
from pyrates.backend.numpy_backend import NumpyBackend
from pyrates.backend import parse_dict
from pyrates.backend.parser import parse_equations

# define test equations
equations = ["a = 5. + 2.", # simple update of variable
"d/dt * a = 5. + 2.", # simple differential equation
equations = ["a = 5. + 2.", # simple update of variable
"d/dt * a = 5. + 2.", # simple differential equation
]

# define equation variables
Expand All @@ -473,11 +493,10 @@ def test_1_7_equation_parsing():

# test equation parser on different test equations
for eq, args, target in zip(equations, arguments, results):

# tensorflow-based parsing
result_tmp = parse_equations(equations=[[(eq, 'node/op')]], equation_args=args, backend=b)['node/op/a']
result = result_tmp.numpy() if hasattr(result_tmp, 'numpy') else result_tmp.eval().numpy()
#assert result == pytest.approx(target, rel=1e-6)
# assert result == pytest.approx(target, rel=1e-6)

# test equation solving of numpy-based parser
#############################################
Expand All @@ -490,7 +509,6 @@ def test_1_7_equation_parsing():

# test equation parser on different test equations
for eq, args, target in zip(equations, arguments, results):

# numpy-based parsing
result = parse_equations(equations=[[(eq, 'node/op')]], equation_args=args, backend=b)['node/op/a']
#assert result == pytest.approx(target, rel=1e-6)
# assert result == pytest.approx(target, rel=1e-6)
16 changes: 12 additions & 4 deletions tests/test_compute_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
import numpy as np
import pytest

# pyrates internal imports
from pyrates.backend import ComputeGraph
from pyrates.frontend import CircuitTemplate

# meta infos
__author__ = "Richard Gast, Daniel Rose"
__status__ = "Development"
Expand Down Expand Up @@ -62,6 +58,9 @@ def test_2_1_operator():
--------
:method:`add_operator`: Detailed documentation of method for adding operations to instance of `ComputeGraph`.
"""
# pyrates internal imports
from pyrates.backend import ComputeGraph
from pyrates.frontend import CircuitTemplate

backends = ["tensorflow", "numpy"]
accuracy = 1e-4
Expand Down Expand Up @@ -165,6 +164,9 @@ def test_2_2_node():
--------
:method:`add_node`: Detailed documentation of method for adding nodes to instance of `ComputeGraph`.
"""
# pyrates internal imports
from pyrates.backend import ComputeGraph
from pyrates.frontend import CircuitTemplate

backends = ['numpy', 'tensorflow']

Expand Down Expand Up @@ -265,6 +267,9 @@ def test_2_3_edge():
:method:`add_edge`: Detailed documentation of add_edge method of `ComputeGraph`class.
"""
# pyrates internal imports
from pyrates.backend import ComputeGraph
from pyrates.frontend import CircuitTemplate

backends = ['numpy', 'tensorflow']
accuracy = 1e-4
Expand Down Expand Up @@ -380,6 +385,9 @@ def test_2_4_vectorization():
--------
:method:`_vectorize`: Detailed documentation of vectorize method of `ComputeGraph` class.
"""
# pyrates internal imports
from pyrates.backend import ComputeGraph
from pyrates.frontend import CircuitTemplate

backends = ['tensorflow', 'numpy']
for b in backends:
Expand Down
Loading

0 comments on commit 494b3e8

Please sign in to comment.