diff --git a/Orange/widgets/tests/base.py b/Orange/widgets/tests/base.py index b7eaa1f2173..10030b7e156 100644 --- a/Orange/widgets/tests/base.py +++ b/Orange/widgets/tests/base.py @@ -1,10 +1,13 @@ import unittest +import numpy as np + from PyQt4.QtGui import (QApplication, QComboBox, QSpinBox, QDoubleSpinBox, QSlider) import sip from Orange.data import Table +from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME, FLAGGED_FEATURE_NAME from Orange.preprocess import RemoveNaNColumns, Randomize from Orange.preprocess.preprocess import PreprocessorList from Orange.classification.base_classification import (LearnerClassification, @@ -453,3 +456,70 @@ def test_parameters(self): self.assertFalse(self.widget.Error.active) else: self.assertTrue(self.widget.Error.active) + + +class WidgetOutputsTestMixin: + """Class for widget's outputs testing. + + Contains init method to set up testing parameters and a test method, which + checks Selected Data and Flagged Data outputs. + + Since widgets have different ways of selecting data instances, _select_data + method should be implemented when subclassed. + + If output's expected domain differs from input's domain, parameter + same_input_output_domain should be set to False. + + If Selected Data and Flagged Data domains differ, override method + _compare_selected_flagged_domains. + """ + + def init(self): + self.data = Table("iris") + self.same_input_output_domain = True + + def test_outputs(self): + self.send_signal(self.signal_name, self.signal_data) + + # only needed in TestOWMDS + if type(self).__name__ == "TestOWMDS": + from PyQt4.QtCore import QEvent + self.widget.customEvent(QEvent(QEvent.User)) + self.widget.commit() + + # check selected data output + self.assertIsNone(self.get_output("Selected Data")) + + # check flagged data output + flagged = self.get_output(FLAGGED_SIGNAL_NAME) + self.assertEqual(0, np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) + + # select data instances + self._select_data() + + # check selected data output + selected = self.get_output("Selected Data") + self.assertGreater(len(selected), 0) + if self.same_input_output_domain: + self.assertEqual(selected.domain, self.data.domain) + + # check flagged data output + flagged = self.get_output(FLAGGED_SIGNAL_NAME) + self.assertEqual(len(selected), + np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) + + # compare selected and flagged data domains + self._compare_selected_flagged_domains(selected, flagged) + + # check output when data is removed + self.send_signal(self.signal_name, None) + self.assertIsNone(self.get_output("Selected Data")) + self.assertIsNone(self.get_output(FLAGGED_SIGNAL_NAME)) + + def _select_data(self): + raise NotImplementedError("Subclasses should implement select_data") + + def _compare_selected_flagged_domains(self, selected, flagged): + selected_vars = selected.domain.variables + selected.domain.metas + flagged_vars = flagged.domain.variables + flagged.domain.metas + self.assertTrue(all((var in flagged_vars for var in selected_vars))) diff --git a/Orange/widgets/unsupervised/tests/test_owdistancemap.py b/Orange/widgets/unsupervised/tests/test_owdistancemap.py index c2ca41760c1..0ea795573c1 100644 --- a/Orange/widgets/unsupervised/tests/test_owdistancemap.py +++ b/Orange/widgets/unsupervised/tests/test_owdistancemap.py @@ -1,50 +1,24 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring import random -import numpy as np -from Orange.data import Table -from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME, FLAGGED_FEATURE_NAME from Orange.distance import Euclidean from Orange.widgets.unsupervised.owdistancemap import OWDistanceMap -from Orange.widgets.tests.base import WidgetTest +from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin -class TestOWDistanceMap(WidgetTest): - def setUp(self): - self.widget = self.create_widget(OWDistanceMap) - self.iris = Table("iris") - self.iris_distances = Euclidean(self.iris) - - def test_outputs(self): - self.send_signal("Distances", self.iris_distances) +class TestOWDistanceMap(WidgetTest, WidgetOutputsTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + WidgetOutputsTestMixin.init(cls) - # check selected data output - self.assertIsNone(self.get_output("Selected Data")) + cls.signal_name = "Distances" + cls.signal_data = Euclidean(cls.data) - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(0, np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) + def setUp(self): + self.widget = self.create_widget(OWDistanceMap) - # select data points - points = random.sample(range(0, len(self.iris)), 20) + def _select_data(self): + points = random.sample(range(0, len(self.data)), 20) self.widget._selection = points self.widget.commit() - - # check selected data output - selected = self.get_output("Selected Data") - self.assertEqual(len(selected), len(points)) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(len(selected), - np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) - - # compare selected and flagged data domains - selected_vars = selected.domain.variables + selected.domain.metas - flagged_vars = flagged.domain.variables + flagged.domain.metas - self.assertTrue(all((var in flagged_vars for var in selected_vars))) - - # check output when data is removed - self.send_signal("Distances", None) - self.assertIsNone(self.get_output("Selected Data")) - self.assertIsNone(self.get_output(FLAGGED_SIGNAL_NAME)) diff --git a/Orange/widgets/unsupervised/tests/test_owhierarchicalclustering.py b/Orange/widgets/unsupervised/tests/test_owhierarchicalclustering.py index f80ec683177..1f6187ffeb3 100644 --- a/Orange/widgets/unsupervised/tests/test_owhierarchicalclustering.py +++ b/Orange/widgets/unsupervised/tests/test_owhierarchicalclustering.py @@ -1,45 +1,32 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring -import numpy as np -from Orange.data import Table -from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME, FLAGGED_FEATURE_NAME +from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME from Orange.distance import Euclidean from Orange.widgets.unsupervised.owhierarchicalclustering import \ OWHierarchicalClustering -from Orange.widgets.tests.base import WidgetTest +from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin -class TestOWHierarchicalClustering(WidgetTest): - def setUp(self): - self.widget = self.create_widget(OWHierarchicalClustering) - self.iris = Table("iris") - self.iris_distances = Euclidean(self.iris) - - def test_outputs(self): - self.send_signal("Distances", self.iris_distances) +class TestOWHierarchicalClustering(WidgetTest, WidgetOutputsTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + WidgetOutputsTestMixin.init(cls) - # check selected data output - self.assertIsNone(self.get_output("Selected Data")) + cls.distances = Euclidean(cls.data) + cls.signal_name = "Distances" + cls.signal_data = cls.distances + cls.same_input_output_domain = False - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(0, np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) + def setUp(self): + self.widget = self.create_widget(OWHierarchicalClustering) - # select a cluster + def _select_data(self): items = self.widget.dendrogram._items cluster = items[next(iter(items))] self.widget.dendrogram.set_selected_items([cluster]) - # check selected data output - selected = self.get_output("Selected Data") - self.assertGreater(len(selected), 0) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(len(selected), - np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) - - # compare selected and flagged data domains + def _compare_selected_flagged_domains(self, selected, flagged): self.assertTrue(all((var in flagged.domain.variables for var in selected.domain.variables))) self.assertNotIn("Other", selected.domain.metas[0].values) @@ -48,14 +35,9 @@ def test_outputs(self): all((var in [var.name for var in flagged.domain.metas] for var in [var.name for var in selected.domain.metas]))) - # check output when data is removed - self.send_signal("Distances", None) - self.assertIsNone(self.get_output("Selected Data")) - self.assertIsNone(self.get_output(FLAGGED_SIGNAL_NAME)) - def test_selection_box_output(self): """Check output if Selection method changes""" - self.send_signal("Distances", self.iris_distances) + self.send_signal("Distances", self.distances) self.assertIsNone(self.get_output("Selected Data")) self.assertIsNotNone(self.get_output(FLAGGED_SIGNAL_NAME)) diff --git a/Orange/widgets/unsupervised/tests/test_owmds.py b/Orange/widgets/unsupervised/tests/test_owmds.py index 2c4168a4778..9c12d920b74 100644 --- a/Orange/widgets/unsupervised/tests/test_owmds.py +++ b/Orange/widgets/unsupervised/tests/test_owmds.py @@ -1,53 +1,25 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring import random -import numpy as np -from PyQt4.QtCore import QEvent -from Orange.data import Table -from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME, FLAGGED_FEATURE_NAME from Orange.distance import Euclidean from Orange.widgets.unsupervised.owmds import OWMDS -from Orange.widgets.tests.base import WidgetTest +from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin -class TestOWMDS(WidgetTest): - def setUp(self): - self.widget = self.create_widget(OWMDS) - self.iris = Table("iris") - self.iris_distances = Euclidean(self.iris) +class TestOWMDS(WidgetTest, WidgetOutputsTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + WidgetOutputsTestMixin.init(cls) - def test_outputs(self): - self.send_signal("Distances", self.iris_distances) - self.widget.customEvent(QEvent(QEvent.User)) - self.widget.commit() + cls.signal_name = "Distances" + cls.signal_data = Euclidean(cls.data) + cls.same_input_output_domain = False - # check selected data output - self.assertIsNone(self.get_output("Selected Data")) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(0, np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) + def setUp(self): + self.widget = self.create_widget(OWMDS) - # select data points - points = random.sample(range(0, len(self.iris)), 20) + def _select_data(self): + points = random.sample(range(0, len(self.data)), 20) self.widget.select_indices(points) self.widget.commit() - - # check selected data output - selected = self.get_output("Selected Data") - self.assertEqual(len(selected), len(points)) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(len(selected), - np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) - - # compare selected and flagged data domains - selected_vars = selected.domain.variables + selected.domain.metas - flagged_vars = flagged.domain.variables + flagged.domain.metas - self.assertTrue(all((var in flagged_vars for var in selected_vars))) - - # check output when data is removed - self.send_signal("Distances", None) - self.assertIsNone(self.get_output("Selected Data")) - self.assertIsNone(self.get_output(FLAGGED_SIGNAL_NAME)) diff --git a/Orange/widgets/visualize/tests/test_owscatterplot.py b/Orange/widgets/visualize/tests/test_owscatterplot.py index fe659c8a8f9..adcba48f56b 100644 --- a/Orange/widgets/visualize/tests/test_owscatterplot.py +++ b/Orange/widgets/visualize/tests/test_owscatterplot.py @@ -5,32 +5,38 @@ from PyQt4.QtCore import QRectF from Orange.data import Table, Domain, ContinuousVariable, DiscreteVariable -from Orange.misc.flagged_data import FLAGGED_SIGNAL_NAME, FLAGGED_FEATURE_NAME -from Orange.widgets.tests.base import WidgetTest +from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin from Orange.widgets.visualize.owscatterplot import \ OWScatterPlot, ScatterPlotVizRank -class TestOWScatterPlot(WidgetTest): +class TestOWScatterPlot(WidgetTest, WidgetOutputsTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + WidgetOutputsTestMixin.init(cls) + + cls.signal_name = "Data" + cls.signal_data = cls.data + def setUp(self): self.widget = self.create_widget(OWScatterPlot) - self.iris = Table("iris") def test_set_data(self): # Connect iris to scatter plot - self.send_signal("Data", self.iris) + self.send_signal("Data", self.data) # First two attribute should be selected as x an y - self.assertEqual(self.widget.attr_x, self.iris.domain[0].name) - self.assertEqual(self.widget.attr_y, self.iris.domain[1].name) + self.assertEqual(self.widget.attr_x, self.data.domain[0].name) + self.assertEqual(self.widget.attr_y, self.data.domain[1].name) # Class var should be selected as color self.assertEqual(self.widget.graph.attr_color, - self.iris.domain.class_var.name) + self.data.domain.class_var.name) # Change which attributes are displayed - self.widget.attr_x = self.iris.domain[2].name - self.widget.attr_y = self.iris.domain[3].name + self.widget.attr_x = self.data.domain[2].name + self.widget.attr_y = self.data.domain[3].name # Disconnect the data self.send_signal("Data", None) @@ -45,10 +51,10 @@ def test_set_data(self): # Connect iris again # same attributes that were used last time should be selected - self.send_signal("Data", self.iris) + self.send_signal("Data", self.data) - self.assertEqual(self.widget.attr_x, self.iris.domain[2].name) - self.assertEqual(self.widget.attr_y, self.iris.domain[3].name) + self.assertEqual(self.widget.attr_x, self.data.domain[2].name) + self.assertEqual(self.widget.attr_y, self.data.domain[3].name) def test_score_heuristics(self): domain = Domain([ContinuousVariable(c) for c in "abcd"], @@ -61,42 +67,17 @@ def test_score_heuristics(self): list("abcd")) def test_optional_combos(self): - domain = self.iris.domain + domain = self.data.domain d1 = Domain(domain.attributes[:2], domain.class_var, [domain.attributes[2]]) - t1 = Table(d1, self.iris) + t1 = Table(d1, self.data) self.send_signal("Data", t1) self.widget.graph.attr_size = domain.attributes[2].name d2 = Domain(domain.attributes[:2], domain.class_var, [domain.attributes[3]]) - t2 = Table(d2, self.iris) + t2 = Table(d2, self.data) self.send_signal("Data", t2) - def test_outputs(self): - self.send_signal("Data", self.iris) - - # check selected data output - self.assertIsNone(self.get_output("Selected Data")) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(0, np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) - - # select data points + def _select_data(self): self.widget.graph.select_by_rectangle(QRectF(4, 3, 3, 1)) - - # check selected data output - selected = self.get_output("Selected Data") - self.assertGreater(len(selected), 0) - self.assertEqual(selected.domain, self.iris.domain) - - # check flagged data output - flagged = self.get_output(FLAGGED_SIGNAL_NAME) - self.assertEqual(len(selected), - np.sum([i[FLAGGED_FEATURE_NAME] for i in flagged])) - - # check output when data is removed - self.send_signal("Data", None) - self.assertIsNone(self.get_output("Selected Data")) - self.assertIsNone(self.get_output(FLAGGED_SIGNAL_NAME))