def test_run(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["crossover_rate"] = 0.9 params["max_generations"] = 50 params["mutation_rate"] = 0.06 params["plateau"] = 30 params["population_size"] = 100 params["sample_size"] = 7 params["timeout"] = None params["verbose"] = False seed(1 if sys.version_info.major == 2 else 67) rearrangement = arrange(**params) self.assertEqual(rearrangement, { 'distances': 3.3005630797457695, 'crossings': 1, 'layout': [9, 5, 4, 0, 2, 1, 11, 8, 3, 7, 6, 10] }) expected = u""" AMET, 11> LOREM, 01 CONSECTETUER: adipiscing LOREM: ipsum, dolor, sit DF1, 11 LOREM, 1N SUSPENDISSE SUSPENDISSE: diam CONSECTETUER: elit, sed SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus SEMPER, 0N RISUS, 1N DIGNISSIM DF, 11 RISUS, 0N RISUS MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DIGNISSIM: ligula, massa, varius TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec RISUS: ultricies, _cras, elementum """.strip().replace(" ", "") mcd.set_layout(**rearrangement) result = mcd.get_clauses() self.assertEqual(expected, result)
def test_run(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["crossover_rate"] = 0.9 params["max_generations"] = 50 params["mutation_rate"] = 0.06 params["plateau"] = 30 params["population_size"] = 100 params["sample_size"] = 7 params["timeout"] = None params["verbose"] = False seed(1) expected = u""" RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM DIGNISSIM: ligula, massa, varius MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec CONSECTETUER: elit, sed SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing LOREM: ipsum, dolor, sit DF1, 11 LOREM, 1N SUSPENDISSE SUSPENDISSE: diam """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEquals(rearrangement, { 'distances': 4.640986324787455, 'crossings': 1, 'layout': [10, 11, 7, 3, 6, 2, 1, 8, 9, 5, 4, 0] }) result = mcd.get_clauses_from_layout(**rearrangement) self.assertEquals(expected, result)
def test_2_0_link(self): clauses = u""" CLIENT: Réf. client, Nom, Prénom, Adresse PASSER, 0N CLIENT, 11 COMMANDE : COMMANDE: Num commande, Date, Montant """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(range(size)) self.assertEquals(crossing_count, 0) self.assertEquals(total_distances, 1.0)
def test_optimal_layout(self): clauses = u""" SCELERISQUE LOREM: blandit, elit, ligula EROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue NIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM PELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(range(size)) self.assertEquals(crossing_count, 0) self.assertEquals(total_distances, 0.0)
def test_2_0_link(self): clauses = u""" CLIENT: Réf. client, Nom, Prénom, Adresse PASSER, 0N CLIENT, 11 COMMANDE : COMMANDE: Num commande, Date, Montant """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["multiplicity"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(list(range(size))) self.assertEqual(crossing_count, 0) self.assertEqual(total_distances, 1.0)
def test_no_links(self): clauses = u""" SUSPENDISSE: diam CONSECTETUER: elit, sed LOREM: ipsum, dolor, sit DIGNISSIM: ligula, massa, varius RISUS: ultricies, _cras, elementum """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = False params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(1 if sys.version_info.major == 2 else 458) expected = u""" : CONSECTETUER: elit, sed : LOREM: ipsum, dolor, sit : ::: DIGNISSIM: ligula, massa, varius : : RISUS: ultricies, _cras, elementum : SUSPENDISSE: diam : """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEqual(rearrangement, { 'distances': 0.0, 'layout': [1, 2, 5, 3, 4, 0], 'crossings': 0, }) mcd.set_layout(**rearrangement) result = mcd.get_clauses() self.assertEqual(expected, result)
def test_no_links(self): clauses = u""" SUSPENDISSE: diam CONSECTETUER: elit, sed LOREM: ipsum, dolor, sit DIGNISSIM: ligula, massa, varius RISUS: ultricies, _cras, elementum """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = False params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(1) expected = u""" : CONSECTETUER: elit, sed : LOREM: ipsum, dolor, sit : ::: DIGNISSIM: ligula, massa, varius : : RISUS: ultricies, _cras, elementum : SUSPENDISSE: diam : """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEquals(rearrangement, { 'distances': 0.0, 'layout': [1, 2, 5, 3, 4, 0], 'crossings': 0, }) result = mcd.get_clauses_from_layout(**rearrangement) self.assertEquals(expected, result)
def test_diagonal_reflexive_association(self): clauses = u""" Norm : Draw, Unit, Folk, Peer, Tour, Hall : : Baby, 1N Norm, 0N> Norm """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["multiplicity"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(list(range(size))) self.assertEqual(crossing_count, 0) self.assertEqual(round(total_distances, 4), 0.8284)
def test_k33_better(self): clauses = u""" DIGNISSIM: nec sem, nunc, vulputate RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT IMPERDIET: a praesent, nibh, semper SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT TINCIDUNT: faucibus, orci, cursus QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(range(size)) self.assertEquals(crossing_count, 3)
def test_optimal_layout(self): clauses = u""" SCELERISQUE LOREM: blandit, elit, ligula EROS, 11 SCELERISQUE LOREM, 1N PELLENTESQUE IPSUM: metus, congue NIBH, 1N SCELERISQUE LOREM, 11 PELLENTESQUE IPSUM PELLENTESQUE IPSUM: tincidunt, bibendum, consequat, integer """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["multiplicity"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(list(range(size))) self.assertEqual(crossing_count, 0) self.assertEqual(total_distances, 0.0)
def test_k33_better(self): clauses = u""" DIGNISSIM: nec sem, nunc, vulputate RHONCUS, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT IMPERDIET: a praesent, nibh, semper SODALES, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT TINCIDUNT: faucibus, orci, cursus QUIS ENIM, 1N DIGNISSIM, 1N IMPERDIET, 1N TINCIDUNT """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["multiplicity"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(list(range(size))) self.assertEqual(crossing_count, 3)
def test_optimal_layout_with_reflexive_association(self): clauses = u""" Assistas, 01 Hci poilu, 0N Hci poilu Hci poilu: graffiti, champignon, troussa, graffiti Rayonnait, 0N Hci poilu, 0N Lappa: monobloc Brisa: souffrait Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar Lappa: graffiti, champignon Puni, 11 Lappa, 0N Lappa """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(range(size)) self.assertEquals(crossing_count, 0) self.assertEquals(total_distances, 0.0)
def test_optimal_layout_with_reflexive_association(self): clauses = u""" Assistas, 01 Hci poilu, 0N Hci poilu Hci poilu: graffiti, champignon, troussa, graffiti Rayonnait, 0N Hci poilu, 0N Lappa: monobloc Brisa: souffrait Pillards, 0N Brisa, 0N Lappa, 0N Hci poilu: disions, lascar Lappa: graffiti, champignon Puni, 11 Lappa, 0N Lappa """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) d = mcd.get_layout_data() evaluate = fitness(d["links"], d["multiplicity"], d["col_count"], d["row_count"]) size = d["col_count"] * d["row_count"] (crossing_count, total_distances) = evaluate(list(range(size))) self.assertEqual(crossing_count, 0) self.assertEqual(total_distances, 0.0)
PEAK: amid, salt BOOT, 01 GAME, 0N GAME: snap DIET: iron, cell SOUL, 0N DIET, 0N SLOW: joke ALLY, 1N ODDS, 11 SLOW: whom FUND, 1N LOCK, 1N /ODDS: dump DENY, 0N QUIT, 0N QUIT: hers QUIT: rich, milk MYTH, 11 DIET, 0N QUIT: clip POEM: cute, farm HANG, 1N POEM, _11 ODDS: golf ODDS: echo """.split("\n") params = parsed_arguments() params["title"] = "Untitled" params["guess_title"] = False t = Relations(Mcd(clauses, params), params) class relationTemplatesTest(unittest.TestCase): def test_diagram(self): template = json.loads(codecs.open("mocodo/relation_templates/diagram.json").read()) expected = u""" %%mocodo : : :
from __future__ import division import sys sys.path[0:0] = ["."] import unittest from mocodo.relations import * from mocodo.mcd import Mcd import json from mocodo.file_helpers import read_contents from copy import deepcopy from mocodo.argument_parser import parsed_arguments minimal_template = json.loads(read_contents("mocodo/relation_templates/text.json")) json_template = json.loads(read_contents("mocodo/relation_templates/json.json")) params = parsed_arguments() params["title"] = "Untitled" params["guess_title"] = False # Python 2.7 compatibility if not hasattr(unittest.TestCase, "assertRaisesRegex"): unittest.TestCase.assertRaisesRegex = unittest.TestCase.assertRaisesRegexp class relationsTest(unittest.TestCase): def test_character_cases(self): clauses = u""" Riot: clue Into, 11 Form, 1N Riot: goat Form: land, hide Tuck, 1N Read, 1N Form: thin
def test_non_connected_graph(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = False params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(42 if sys.version_info.major == 2 else 129) rearrangement = arrange(**params) mcd.set_layout(**rearrangement) self.assertEqual( rearrangement, { 'distances': 0.0, 'crossings': 0, 'coords': { 0: (2, 2), 1: (2, 1), 2: (2, 0), 3: (0, 0), 4: (3, 2), 5: (3, 1), 6: (0, 1), 7: (1, 0), 8: (0, 2), 9: (3, 0), 10: (1, 2), 11: (1, 1) }, 'layout': [3, 7, 2, 9, 6, 11, 1, 5, 8, 10, 0, 4] }) expected = u""" MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM : CONSECTETUER: elit, sed AMET, 11> LOREM, 01 CONSECTETUER: adipiscing DIGNISSIM: ligula, massa, varius SEMPER, 0N RISUS, 1N DIGNISSIM SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus LOREM: ipsum, dolor, sit DF, 11 RISUS, 0N RISUS RISUS: ultricies, _cras, elementum SUSPENDISSE: diam DF1, 11 LOREM, 1N SUSPENDISSE """.strip().replace(" ", "") result = mcd.get_clauses() self.assertEqual(expected, result)
def test_organic_rearrangement(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = True params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(1 if sys.version_info.major == 2 else 299) expected = u""" DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit AMET, 11> LOREM, 01 CONSECTETUER: adipiscing : SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM :: TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius :: RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM :: DF, 11 RISUS, 0N RISUS : """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEqual( rearrangement, { 'distances': 0.0, 'layout': [ 4, 5, 9, None, 0, 1, 2, 3, None, None, 6, 7, None, None, 10, 11, None, None, 8, None ], 'crossings': 0, 'col_count': 4, 'row_count': 5, 'coords': { 0: (0, 1), 1: (1, 1), 2: (2, 1), 3: (3, 1), 4: (0, 0), 5: (1, 0), 6: (2, 2), 7: (3, 2), 8: (2, 4), 9: (2, 0), 10: (2, 3), 11: (3, 3) } }) mcd.set_layout(**rearrangement) result = mcd.get_clauses() self.assertEqual(expected, result)
def test_organic_rearrangement(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = True params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(1) expected = u""" DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit AMET, 11> LOREM, 01 CONSECTETUER: adipiscing : SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM :: TORTOR, 0N RISUS, 11 DIGNISSIM, 1N CONSECTETUER: nec DIGNISSIM: ligula, massa, varius :: RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM :: DF, 11 RISUS, 0N RISUS : """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEquals(rearrangement, { 'distances': 0.0, 'layout': [4, 5, 9, None, 0, 1, 2, 3, None, None, 6, 7, None, None, 10, 11, None, None, 8, None], 'crossings': 0, 'col_count': 4, 'row_count': 5, 'coords': { 0: (0, 1), 1: (1, 1), 2: (2, 1), 3: (3, 1), 4: (0, 0), 5: (1, 0), 6: (2, 2), 7: (3, 2), 8: (2, 4), 9: (2, 0), 10: (2, 3), 11: (3, 3) } }) result = mcd.get_clauses_from_layout(**rearrangement) self.assertEquals(expected, result)
def test_non_connected_graph(self): clauses = u""" SUSPENDISSE: diam SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus CONSECTETUER: elit, sed MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM DF1, 11 LOREM, 1N SUSPENDISSE LOREM: ipsum, dolor, sit DIGNISSIM: ligula, massa, varius DF, 11 RISUS, 0N RISUS AMET, 11> LOREM, 01 CONSECTETUER: adipiscing RISUS: ultricies, _cras, elementum SEMPER, 0N RISUS, 1N DIGNISSIM """.replace(" ", "") params = parsed_arguments() mcd = Mcd(clauses.split("\n"), params) params.update(mcd.get_layout_data()) params["organic"] = False params["call_limit"] = 10000 params["max_objective"] = 15 params["min_objective"] = 0 params["timeout"] = None params["verbose"] = False seed(42) expected = u""" MAECENAS, 1N DIGNISSIM, 1N DIGNISSIM : CONSECTETUER: elit, sed AMET, 11> LOREM, 01 CONSECTETUER: adipiscing DIGNISSIM: ligula, massa, varius SEMPER, 0N RISUS, 1N DIGNISSIM SOLLICITUDIN, 0N SUSPENDISSE, 0N CONSECTETUER, 0N LOREM: lectus LOREM: ipsum, dolor, sit DF, 11 RISUS, 0N RISUS RISUS: ultricies, _cras, elementum SUSPENDISSE: diam DF1, 11 LOREM, 1N SUSPENDISSE """.strip().replace(" ", "") rearrangement = arrange(**params) self.assertEquals(rearrangement, { 'distances': 0.0, 'crossings': 0, 'coords': { 0: (2, 2), 1: (2, 1), 2: (2, 0), 3: (0, 0), 4: (3, 2), 5: (3, 1), 6: (0, 1), 7: (1, 0), 8: (0, 2), 9: (3, 0), 10: (1, 2), 11: (1, 1) }, 'layout': [3, 7, 2, 9, 6, 11, 1, 5, 8, 10, 0, 4] }) result = mcd.get_clauses_from_layout(**rearrangement) self.assertEquals(expected, result)