Skip to content

Commit

Permalink
Merge pull request #2520 from ales-erjavec/fixes/async-tests
Browse files Browse the repository at this point in the history
[FIX] Fix asynchronous widget tests
  • Loading branch information
astaric authored Aug 9, 2017
2 parents 3a5d0d4 + 51f47e5 commit 6da33a0
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 15 deletions.
23 changes: 15 additions & 8 deletions Orange/widgets/evaluate/tests/test_owtestlearners.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,28 @@ def setUp(self):
super().setUp()
self.widget = self.create_widget(OWTestLearners) # type: OWTestLearners

def tearDown(self):
self.widget.onDeleteWidget()
super().tearDown()

def test_basic(self):
data = Table("iris")[::3]
data = Table("iris")[::15]
self.send_signal(self.widget.Inputs.train_data, data)
self.send_signal(self.widget.Inputs.learner, MajorityLearner(), 0, wait=5000)
res = self.get_output(self.widget.Outputs.evaluations_results)
self.send_signal(self.widget.Inputs.learner, MajorityLearner(), 0)
res = self.get_output(self.widget.Outputs.evaluations_results, wait=5000)
self.assertIsInstance(res, Results)
self.assertIsNotNone(res.domain)
self.assertIsNotNone(res.data)
self.assertIsNotNone(res.probabilities)

self.send_signal(self.widget.Inputs.learner, None, 0, wait=5000)
res = self.get_output(self.widget.Outputs.evaluations_results)
self.send_signal(self.widget.Inputs.learner, None, 0)
res = self.get_output(self.widget.Outputs.evaluations_results, wait=5000)
self.assertIsNone(res)

data = Table("housing")[::10]
self.send_signal(self.widget.Inputs.train_data, data)
self.send_signal(self.widget.Inputs.learner, MeanLearner(), 0, wait=5000)
res = self.get_output(self.widget.Outputs.evaluations_results)
self.send_signal(self.widget.Inputs.learner, MeanLearner(), 0)
res = self.get_output(self.widget.Outputs.evaluations_results, wait=5000)
self.assertIsInstance(res, Results)
self.assertIsNotNone(res.domain)
self.assertIsNotNone(res.data)
Expand All @@ -65,6 +69,7 @@ def test_CrossValidationByFeature(self):
self.send_signal(self.widget.Inputs.train_data, data)
self.assertFalse(rb.isEnabled())
self.assertFalse(self.widget.features_combo.isEnabled())
self.get_output(self.widget.Outputs.evaluations_results, wait=5000)

self.send_signal(self.widget.Inputs.train_data, data_with_disc_metas)
self.assertTrue(rb.isEnabled())
Expand All @@ -73,6 +78,7 @@ def test_CrossValidationByFeature(self):
self.assertTrue(self.widget.features_combo.isEnabled())
self.assertEqual(self.widget.features_combo.currentText(), "iris")
self.assertEqual(len(self.widget.features_combo.model()), 1)
self.get_output(self.widget.Outputs.evaluations_results, wait=5000)

self.send_signal(self.widget.Inputs.train_data, None)
self.assertFalse(rb.isEnabled())
Expand Down Expand Up @@ -148,7 +154,7 @@ def test_memory_error(self):
Handling memory error.
GH-2316
"""
data = Table("iris")[::3]
data = Table("iris")[::15]
self.send_signal(self.widget.Inputs.train_data, data)
self.assertFalse(self.widget.Error.memory_error.is_shown())

Expand Down Expand Up @@ -217,6 +223,7 @@ class NewRegressionScore(RegressionScore):
del Score.registry["NewClassificationScore"]
del Score.registry["NewRegressionScore"]


class TestHelpers(unittest.TestCase):
def test_results_one_vs_rest(self):
data = Table("lenses")
Expand Down
23 changes: 20 additions & 3 deletions Orange/widgets/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import time
import unittest
from unittest.mock import Mock
# pylint: disable=unused-import
from typing import List, Optional, Type, TypeVar

import numpy as np
import sip
Expand All @@ -28,6 +30,7 @@
from Orange.widgets.utils.annotated_data import (
ANNOTATED_DATA_FEATURE_NAME, ANNOTATED_DATA_SIGNAL_NAME
)
from Orange.widgets.widget import OWWidget
from Orange.widgets.utils.owlearnerwidget import OWBaseLearner

sip.setdestroyonexit(False)
Expand All @@ -36,6 +39,9 @@

DEFAULT_TIMEOUT = 5000

# pylint: disable=invalid-name
T = TypeVar("T")


class DummySignalManager:
def __init__(self):
Expand Down Expand Up @@ -70,8 +76,7 @@ class WidgetTest(GuiTest):
will ensure they are created correctly.
"""

#: list[OwWidget]
widgets = []
widgets = [] # type: List[OWWidget]

@classmethod
def setUpClass(cls):
Expand All @@ -95,6 +100,7 @@ def tearDown(self):
self.process_events()

def create_widget(self, cls, stored_settings=None, reset_default_settings=True):
# type: (Type[T], Optional[dict], bool) -> T
"""Create a widget instance using mock signal_manager.
When used with default parameters, it also overrides settings stored
Expand Down Expand Up @@ -215,31 +221,42 @@ def send_signal(self, input, value, *args, widget=None, wait=-1):
else:
raise ValueError("'{}' is not an input name for widget {}"
.format(input, type(widget).__name__))
if widget.isBlocking():
raise RuntimeError("'send_signal' called but the widget is in "
"blocking state and does not accept inputs.")
getattr(widget, input.handler)(value, *args)
widget.handleNewSignals()
if wait >= 0 and widget.isBlocking():
spy = QSignalSpy(widget.blockingStateChanged)
self.assertTrue(spy.wait(timeout=wait))

def get_output(self, output, widget=None):
def get_output(self, output, widget=None, wait=5000):
"""Return the last output that has been sent from the widget.
Parameters
----------
output_name : str
widget : Optional[OWWidget]
widget whose output is returned. If not set, self.widget is used
wait : int
The amount of time (in milliseconds) to wait for widget to complete.
Returns
-------
The last sent value of given output or None if nothing has been sent.
"""
if widget is None:
widget = self.widget

if widget.isBlocking() and wait >= 0:
spy = QSignalSpy(widget.blockingStateChanged)
self.assertTrue(spy.wait(wait),
"Failed to get output in the specified timeout")
if not isinstance(output, str):
output = output.name
return self.signal_manager.outputs.get((widget, output), None)


@contextmanager
def modifiers(self, modifiers):
"""
Expand Down
12 changes: 8 additions & 4 deletions Orange/widgets/unsupervised/tests/test_owmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def setUp(self):
}
) # type: OWMDS

def tearDown(self):
self.widget.onDeleteWidget()
super().tearDown()

def _select_data(self):
random.seed(42)
points = random.sample(range(0, len(self.data)), 20)
Expand All @@ -37,8 +41,8 @@ def _select_data(self):
return sorted(points)

def test_pca_init(self):
self.send_signal(self.signal_name, self.signal_data, wait=1000)
output = self.get_output(self.widget.Outputs.annotated_data)
self.send_signal(self.signal_name, self.signal_data)
output = self.get_output(self.widget.Outputs.annotated_data, wait=1000)
expected = np.array(
[[-2.69304803, 0.32676458],
[-2.7246721, -0.20921726],
Expand All @@ -49,7 +53,7 @@ def test_pca_init(self):

def test_nan_plot(self):
data = datasets.missing_data_1()
self.send_signal(self.widget.Inputs.data, data)
self.send_signal(self.widget.Inputs.data, data, wait=1000)

simulate.combobox_run_through_all(self.widget.cb_color_value)
simulate.combobox_run_through_all(self.widget.cb_color_value)
Expand All @@ -63,7 +67,7 @@ def test_nan_plot(self):
data.Y[:] = np.nan
data.metas[:, 1] = np.nan

self.send_signal("Data", data)
self.send_signal("Data", data, wait=1000)

simulate.combobox_run_through_all(self.widget.cb_color_value)
simulate.combobox_run_through_all(self.widget.cb_shape_value)
Expand Down

0 comments on commit 6da33a0

Please sign in to comment.