def test_concatenate(self): """Test string concatenation.""" # Define grammar rules excel_reference_prefix = "=" excel_prefix = "CONCATENATE(" excel_separator = "," excel_suffix = ")" python_reference_prefix = "" python_numpy_separator = "+" # A) Anchored a_res_cell = self.a_operand_1.concatenate(self.a_operand_2) # Compare words a_res_parsed = a_res_cell.parse self.assertEqual((excel_reference_prefix + excel_prefix + self.coord_operand_1_excel + excel_separator + self.coord_operand_2_excel + excel_suffix), a_res_parsed['excel']) self.assertEqual( (python_reference_prefix + self.coord_operand_1_python + python_numpy_separator + self.coord_operand_2_python), a_res_parsed['python_numpy']) # Compare results of anchored self.assertAlmostEqual( a_res_cell.value, str(self.a_operand_1.value) + str(self.a_operand_2.value)) # B) Un-anchored, numerical u_res_cell = self.u_operand_1.concatenate(self.u_operand_2) # Compare words u_res_parsed = u_res_cell.parse self.assertEqual( u_res_parsed['excel'], (excel_reference_prefix + excel_prefix + self.value_u_1 + excel_separator + self.value_u_2 + excel_suffix)) self.assertEqual( u_res_parsed['python_numpy'], ('"' + python_reference_prefix + self.value_u_1 + '"' + python_numpy_separator + '"' + self.value_u_2 + '"')) # Compare results of un-anchored self.assertAlmostEqual( u_res_cell.value, str(self.u_operand_1.value) + str(self.u_operand_2.value)) # C) Un-anchored, strings str_value = "6ppW1lPT" u_operand_1 = Cell(value=str_value, cell_indices=self.cell_indices) u_res_cell = u_operand_1.concatenate(self.u_operand_2) # Compare words u_res_parsed = u_res_cell.parse self.assertEqual( u_res_parsed['excel'], (excel_reference_prefix + excel_prefix + '"' + str_value + '"' + excel_separator + self.value_u_2 + excel_suffix)) self.assertEqual(u_res_parsed['python_numpy'], (python_reference_prefix + str_value + python_numpy_separator + '"' + self.value_u_2 + '"')) # Compare results of un-anchored self.assertAlmostEqual(u_res_cell.value, u_operand_1.value + str(self.u_operand_2.value))
class TestCellBinaryOperations(unittest.TestCase): """Test binary operations. Notice: if variable start with prefix 'a_' it means that cell is anchored (located in grid), if with prefix 'u_' it means that it is NOT anchored, with prefix 't' it does not matter (just a testing variable). """ def setUp(self) -> None: self.cell_indices: CellIndices = CellIndices(5, 7) self.a_operand_1 = Cell(3, 4, 7, cell_indices=self.cell_indices) self.a_operand_2 = Cell(2, 4, 4, cell_indices=self.cell_indices) self.coord_operand_1_python = "values[3,4]" self.coord_operand_2_python = "values[2,4]" self.coord_operand_1_excel = "F5" self.coord_operand_2_excel = "F4" self.u_operand_1 = Cell(value=7, cell_indices=self.cell_indices) self.u_operand_2 = Cell(value=8, cell_indices=self.cell_indices) self.value_u_1 = "7" self.value_u_2 = "8" def _check_binary_operation( self, operation_method: Callable[[Cell, Cell], Cell], real_operation_fn: Callable[[float, float], float], excel_separator: str, python_numpy_separator: str, *, excel_prefix: str = "", excel_suffix: str = "", excel_reference_prefix: str = "=", python_reference_prefix: str = "", ) -> None: """Run the binary operation, compare numeric result, compare words. Args: operation_method (Callable[[Cell, Cell], Cell]): Pointer to the method inside the Cell class. real_operation_fn (Callable[[float, float], float]): Pointer to the Python method that compute the same. excel_separator (str): Separator of the operation in Excel language. python_numpy_separator (str): Separator of the operation in Python_NumPY language. excel_prefix (str): Prefix for the operation in Excel language. excel_suffix (str): Suffix for the operation in Excel language. excel_reference_prefix (str): Prefix of the word that reference to some computation in Excel. python_reference_prefix (str): Prefix of the word that reference to some computation in Python. """ # A) Anchored a_res_cell = operation_method(self.a_operand_1, self.a_operand_2) # Compare words a_res_parsed = a_res_cell.parse self.assertEqual(a_res_parsed['excel'], (excel_reference_prefix + excel_prefix + self.coord_operand_1_excel + excel_separator + self.coord_operand_2_excel + excel_suffix)) self.assertEqual( a_res_parsed['python_numpy'], (python_reference_prefix + self.coord_operand_1_python + python_numpy_separator + self.coord_operand_2_python)) # Compare results of anchored self.assertAlmostEqual( a_res_cell.value, real_operation_fn(self.a_operand_1.value, self.a_operand_2.value)) # B) Un-anchored u_res_cell = operation_method(self.u_operand_1, self.u_operand_2) # Compare words u_res_parsed = u_res_cell.parse self.assertEqual( u_res_parsed['excel'], (excel_reference_prefix + excel_prefix + self.value_u_1 + excel_separator + self.value_u_2 + excel_suffix)) self.assertEqual(u_res_parsed['python_numpy'], (python_reference_prefix + self.value_u_1 + python_numpy_separator + self.value_u_2)) # Compare results of un-anchored self.assertAlmostEqual( u_res_cell.value, real_operation_fn(self.u_operand_1.value, self.u_operand_2.value)) def test_string_equal(self): """Test if the strings are interpreted correctly in operations""" u_operand_str = Cell(None, None, "abc", cell_indices=self.cell_indices) comp = (self.a_operand_1 == u_operand_str) self.assertEqual(comp.parse['python_numpy'], 'values[3,4]=="abc"') self.assertEqual(comp.parse['excel'], '=F5="abc"') def test_add(self): """Test adding""" # Method test self._check_binary_operation(Cell.add, lambda x, y: x + y, "+", "+") # Operator test self._check_binary_operation(Cell.__add__, lambda x, y: x + y, "+", "+") def test_subtract(self): """Test subtracting""" # Method test self._check_binary_operation(Cell.subtract, lambda x, y: x - y, "-", "-") # Operator test self._check_binary_operation(Cell.__sub__, lambda x, y: x - y, "-", "-") def test_multiply(self): """Test multiplying""" # Method test self._check_binary_operation(Cell.multiply, lambda x, y: x * y, "*", "*") # Operator test self._check_binary_operation(Cell.__mul__, lambda x, y: x * y, "*", "*") def test_divide(self): """Test dividing""" # Method test self._check_binary_operation(Cell.divide, lambda x, y: x / y, "/", "/") # Operator test self._check_binary_operation(Cell.__truediv__, lambda x, y: x / y, "/", "/") def test_modulo(self): """Test modulo""" # Method test self._check_binary_operation(Cell.modulo, lambda x, y: x % y, ",", "%", excel_prefix="MOD(", excel_suffix=")") # Operator test self._check_binary_operation(Cell.__mod__, lambda x, y: x % y, ",", "%", excel_prefix="MOD(", excel_suffix=")") def test_power(self): """Test power""" # Method test self._check_binary_operation(Cell.power, lambda x, y: x**y, "^", "**") # Operator test self._check_binary_operation(Cell.__pow__, lambda x, y: x**y, "^", "**") def test_equalTo(self): """Test equal to""" # Method test self._check_binary_operation(Cell.equalTo, lambda x, y: x == y, "=", "==") # Operator test self._check_binary_operation(Cell.__eq__, lambda x, y: x == y, "=", "==") def test_notEqualTo(self): """Test not equal to""" # Method test self._check_binary_operation(Cell.notEqualTo, lambda x, y: x != y, "<>", "!=") # Operator test self._check_binary_operation(Cell.__ne__, lambda x, y: x != y, "<>", "!=") def test_greaterThan(self): """Test greater than""" # Method test self._check_binary_operation(Cell.greaterThan, lambda x, y: x > y, ">", ">") # Operator test self._check_binary_operation(Cell.__gt__, lambda x, y: x > y, ">", ">") def test_greaterThanOrEqualTo(self): """Test greater than or equal to""" # Method test self._check_binary_operation(Cell.greaterThanOrEqualTo, lambda x, y: x >= y, ">=", ">=") # Operator test self._check_binary_operation(Cell.__ge__, lambda x, y: x >= y, ">=", ">=") def test_lessThan(self): """Test less than""" # Method test self._check_binary_operation(Cell.lessThan, lambda x, y: x < y, "<", "<") # Operator test self._check_binary_operation(Cell.__lt__, lambda x, y: x < y, "<", "<") def test_lessThanOrEqualTo(self): """Test less than or equal to""" # Method test self._check_binary_operation(Cell.lessThanOrEqualTo, lambda x, y: x <= y, "<=", "<=") # Operator test self._check_binary_operation(Cell.__le__, lambda x, y: x <= y, "<=", "<=") def test_LogicalConjunction(self): """Test logical conjunction""" # Method test self._check_binary_operation(Cell.logicalConjunction, lambda x, y: x and y, ", ", " and ", excel_prefix="AND(", excel_suffix=")") # Operator test self._check_binary_operation(Cell.__and__, lambda x, y: x and y, ", ", " and ", excel_prefix="AND(", excel_suffix=")") def test_LogicalDisjunction(self): """Test logical disjunction""" # Method test self._check_binary_operation(Cell.logicalDisjunction, lambda x, y: x or y, ", ", " or ", excel_prefix="OR(", excel_suffix=")") # Operator test self._check_binary_operation(Cell.__or__, lambda x, y: x or y, ", ", " or ", excel_prefix="OR(", excel_suffix=")") def test_chain_of_operation(self): """Test multiple operations in a sequence""" result = self.a_operand_1 + self.a_operand_2 * self.u_operand_1 self.assertDictEqual( { 'python_numpy': 'values[3,4]+values[2,4]*7', 'excel': '=F5+F4*7' }, result.parse) self.assertAlmostEqual(result.value, 35) def test_raw_statement(self): """Test raw statement""" result = Cell.raw(self.a_operand_1, { 'python_numpy': "Hello from Python", 'excel': "Excel welcomes" }) self.assertDictEqual( { 'python_numpy': "Hello from Python", 'excel': "=Excel welcomes" # Always computational }, result.parse) self.assertAlmostEqual(self.a_operand_1.value, 7) def test_linear_interpolation(self): """Test the linear interpolation""" self.a_operand_1._value = 1 self.a_operand_2._value = 3 self.u_operand_1._value = 9 res = Cell.linear_interpolation(self.a_operand_1, self.a_operand_2, self.a_operand_2, self.u_operand_1, self.u_operand_1) self.assertAlmostEqual(res.value, 27) self.assertDictEqual( { 'python_numpy': 'np.interp(9, [values[3,4], values[2,4]], ' '[values[2,4], 9])', 'excel': '=(9-F4)*((9-F4)/(F4-F5))+9' }, res.parse) def test_concatenate(self): """Test string concatenation.""" # Define grammar rules excel_reference_prefix = "=" excel_prefix = "CONCATENATE(" excel_separator = "," excel_suffix = ")" python_reference_prefix = "" python_numpy_separator = "+" # A) Anchored a_res_cell = self.a_operand_1.concatenate(self.a_operand_2) # Compare words a_res_parsed = a_res_cell.parse self.assertEqual((excel_reference_prefix + excel_prefix + self.coord_operand_1_excel + excel_separator + self.coord_operand_2_excel + excel_suffix), a_res_parsed['excel']) self.assertEqual( (python_reference_prefix + self.coord_operand_1_python + python_numpy_separator + self.coord_operand_2_python), a_res_parsed['python_numpy']) # Compare results of anchored self.assertAlmostEqual( a_res_cell.value, str(self.a_operand_1.value) + str(self.a_operand_2.value)) # B) Un-anchored, numerical u_res_cell = self.u_operand_1.concatenate(self.u_operand_2) # Compare words u_res_parsed = u_res_cell.parse self.assertEqual( u_res_parsed['excel'], (excel_reference_prefix + excel_prefix + self.value_u_1 + excel_separator + self.value_u_2 + excel_suffix)) self.assertEqual( u_res_parsed['python_numpy'], ('"' + python_reference_prefix + self.value_u_1 + '"' + python_numpy_separator + '"' + self.value_u_2 + '"')) # Compare results of un-anchored self.assertAlmostEqual( u_res_cell.value, str(self.u_operand_1.value) + str(self.u_operand_2.value)) # C) Un-anchored, strings str_value = "6ppW1lPT" u_operand_1 = Cell(value=str_value, cell_indices=self.cell_indices) u_res_cell = u_operand_1.concatenate(self.u_operand_2) # Compare words u_res_parsed = u_res_cell.parse self.assertEqual( u_res_parsed['excel'], (excel_reference_prefix + excel_prefix + '"' + str_value + '"' + excel_separator + self.value_u_2 + excel_suffix)) self.assertEqual(u_res_parsed['python_numpy'], (python_reference_prefix + str_value + python_numpy_separator + '"' + self.value_u_2 + '"')) # Compare results of un-anchored self.assertAlmostEqual(u_res_cell.value, u_operand_1.value + str(self.u_operand_2.value))