def test_factory_matches_keys_and_names(self) -> None: for key, element in fl.FunctionFactory().objects.items(): self.assertEqual(key, element.name) # if it is a function, the name should be contained in # in the methods name if element.type == fl.Function.Element.Type.Function: self.assertIn(key, element.method.__name__)
def test_factory_contains_exactly(self) -> None: FunctionFactoryAssert(self, fl.FunctionFactory()) \ .contains_exactly( {'!', '~', '^', '**', '*', '/', '%', '+', '-', '.+', '.-', 'and', 'or'}, fl.Function.Element.Type.Operator) \ .contains_exactly( {'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'cos', 'cosh', 'eq', 'exp', 'fabs', 'floor', 'fmod', 'ge', 'gt', 'le', 'log', 'log10', 'log1p', 'lt', 'max', 'min', 'neq', 'pi', 'pow', 'round', 'sin', 'sinh', 'sqrt', 'tan', 'tanh'}, fl.Function.Element.Type.Function)
def test_function_operators(self) -> None: FunctionFactoryAssert(self, fl.FunctionFactory()) \ .operation_is( { ("!", (0,)): 1, ("!", (1,)): 0, ("~", (1,)): -1, ("~", (-2,)): 2, ("~", (0,)): 0, ("^", (3, 3)): 27, ("^", (9, 0.5)): 3, ("*", (-2, 3)): -6, ("*", (3, -2)): -6, ("/", (6, 3)): 2, ("/", (3, 6)): 0.5, ("%", (6, 3)): 0, ("%", (3, 6)): 3, ("%", (3.5, 6)): 3.5, ("%", (6, 3.5)): 2.5, ("+", (2, 3)): 5, ("+", (2, -3)): -1, ("-", (2, 3)): -1, ("-", (2, -3)): 5, ("and", (1, 0)): 0, ("and", (1, 1)): 1, ("or", (1, 0)): 1, ("or", (0, 0)): 0, })
def test_factory_precedence(self) -> None: precedence_expected = { 0: 100, 1: 90, 2: 80, 3: 70, 4: 60, 5: 50, 6: 40, 7: 30, 8: 20, 9: 10, 10: 0 } factory = fl.FunctionFactory() for p, e in precedence_expected.items(): self.assertEqual(e, factory._precedence(p))
def test_arity(self) -> None: acceptable: Dict[Type[Exception], Set[str]] = { ZeroDivisionError: {"%", "/", "fmod", "^", "**"}, ValueError: { "acos", "acosh", "asin", "atanh", "fmod", "log", "log10", "log1p", "sqrt", "pow" } } errors = [] def evaluate(function_element: fl.Function.Element, parameters: List[float]) -> None: try: function_element.method(*parameters) except Exception as ex: if not (type(ex) in acceptable and function_element.name in acceptable[type(ex)]): errors.append(ex) print( f"{function_element.name}:" f"{function_element.method.__name__}({parameters}): {ex.__class__}" ) from random import Random random = Random() for element in fl.FunctionFactory().objects.values(): if element.arity == 0: evaluate(element, []) else: for i in range(1000): a = fl.Op.scale(random.randint(0, 100), 0, 100, -10, 10) b = fl.Op.scale(random.randint(0, 100), 0, 100, -10, 10) if element.arity == 1: evaluate(element, [a]) evaluate(element, [b]) else: evaluate(element, [a, a]) evaluate(element, [a, b]) evaluate(element, [b, a]) evaluate(element, [b, b]) self.assertListEqual([], errors)