Skip to content

Commit

Permalink
Merge pull request #1417 from astaric/gui-tests
Browse files Browse the repository at this point in the history
[ENH] Test widgets on travis
  • Loading branch information
kernc authored Jul 14, 2016
2 parents 4a484f6 + fa8f13b commit ee78a7e
Show file tree
Hide file tree
Showing 15 changed files with 444 additions and 51 deletions.
3 changes: 2 additions & 1 deletion Orange/canvas/report/owreport.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ def __init__(self):
self.report_changed = False

index_file = pkg_resources.resource_filename(__name__, "index.html")
self.report_html_template = open(index_file, "r").read()
with open(index_file, "r") as f:
self.report_html_template = f.read()

def _setup_ui_(self):
self.table_model = ReportItemModel(0, len(Column.__members__))
Expand Down
23 changes: 6 additions & 17 deletions Orange/canvas/report/tests/test_report.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import unittest
import pickle
import sys
from PyQt4.QtGui import QApplication, QFont, QBrush
from PyQt4.QtGui import QFont, QBrush
from PyQt4.QtCore import Qt
from Orange.data.table import Table
from Orange.classification import LogisticRegressionLearner
Expand All @@ -11,7 +9,7 @@
from Orange.distance import Euclidean
from Orange.canvas.report.owreport import OWReport
from Orange.widgets import gui
from Orange.widgets.tests.base import GuiTest
from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.classify.owclassificationtree import OWClassificationTree
from Orange.widgets.classify.owclassificationtreegraph import OWClassificationTreeGraph
from Orange.widgets.classify.owknn import OWKNNLearner
Expand Down Expand Up @@ -40,7 +38,6 @@
from Orange.widgets.data.owcolor import OWColor
from Orange.widgets.data.owpreprocess import OWPreprocess
from Orange.widgets.evaluate.owcalibrationplot import OWCalibrationPlot
from Orange.widgets.evaluate.owconfusionmatrix import OWConfusionMatrix
from Orange.widgets.evaluate.owliftcurve import OWLiftCurve
from Orange.widgets.evaluate.owrocanalysis import OWROCAnalysis
from Orange.widgets.evaluate.owtestlearners import OWTestLearners
Expand Down Expand Up @@ -68,26 +65,18 @@
from Orange.widgets.visualize.owvenndiagram import OWVennDiagram


class TestReport(GuiTest):
@unittest.skip('Segfaults. Or something.')
class TestReport(WidgetTest):
def test_report(self):
count = 5
for i in range(count):
rep = OWReport.get_instance()
file = OWFile()
file = self.create_widget(OWFile)
file.create_report_html()
rep.make_report(file)
self.assertEqual(rep.table_model.rowCount(), count)

@unittest.skip("Report extends OWWidget which is not picklable")
def test_report_pickle(self):
rep = OWReport().get_instance()
p = pickle.dumps(rep)
rep2 = pickle.loads(p)
self.assertEqual(type(rep), type(rep2))

def test_report_table(self):
rep = OWReport().get_instance()
rep = OWReport.get_instance()
model = PyTableModel([['x', 1, 2],
['y', 2, 2]])
model.setHorizontalHeaderLabels(['a', 'b', 'c'])
Expand Down Expand Up @@ -131,7 +120,7 @@ def test_report_table(self):


@unittest.skip('Segfaults. Dunno. @astaric says it might be something on the QWidget.')
class TestReportWidgets(GuiTest):
class TestReportWidgets(WidgetTest):
clas_widgets = [OWClassificationTree, OWKNNLearner, OWLogisticRegression,
OWMajority, OWNaiveBayes, OWRandomForest,
OWSVMClassification]
Expand Down
3 changes: 2 additions & 1 deletion Orange/widgets/classify/owadaboost.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def create_learner(self):
return self.LEARNER(
base_estimator=self.base_estimator,
n_estimators=self.n_estimators,
preprocessors=self.preprocessors
preprocessors=self.preprocessors,
algorithm=self.losses[self.algorithm]
)

def set_base_learner(self, model):
Expand Down
20 changes: 11 additions & 9 deletions Orange/widgets/classify/owsvmclassification.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def _add_kernel_box(self):
# Initialize with the widest label to measure max width
self.kernel_eq = self.kernels[-1][1]

self.kernel_box = box = gui.hBox(self.controlArea, "Kernel")
box = gui.hBox(self.controlArea, "Kernel")

buttonbox = gui.radioButtonsInBox(
self.kernel_box = buttonbox = gui.radioButtonsInBox(
box, self, "kernel_type", btnLabels=[k[0] for k in self.kernels],
callback=self._on_kernel_changed, addSpace=20)
buttonbox.layout().setSpacing(10)
Expand Down Expand Up @@ -70,15 +70,15 @@ def _add_optimization_box(self):
self.optimization_box, self, "tol", 1e-6, 1.0, 1e-5,
label="Numerical tolerance:",
decimals=6, alignment=Qt.AlignRight, controlWidth=100,
callback=self.settings_changed
)
callback=self.settings_changed)

def add_main_layout(self):
self._add_type_box()
self._add_kernel_box()
self._add_optimization_box()
self._show_right_kernel()

def _on_kernel_changed(self):
def _show_right_kernel(self):
enabled = [[False, False, False], # linear
[True, True, True], # poly
[True, False, False], # rbf
Expand All @@ -89,6 +89,8 @@ def _on_kernel_changed(self):
for spin, enabled in zip(self._kernel_params, mask):
[spin.box.hide, spin.box.show][enabled]()

def _on_kernel_changed(self):
self._show_right_kernel()
self.settings_changed()

def _report_kernel_parameters(self, items):
Expand All @@ -97,12 +99,12 @@ def _report_kernel_parameters(self, items):
elif self.kernel_type == 1:
items["Kernel"] = \
"Polynomial, ({g:.4} x⋅y + {c:.4})<sup>{d}</sup>".format(
g=self.gamma, c=self.coef0, d=self.degree)
g=self.gamma, c=self.coef0, d=self.degree)
elif self.kernel_type == 2:
items["Kernel"] = "RBF, exp(-{:.4}|x-y|²)".format(self.gamma)
else:
items["Kernel"] = "Sigmoid, tanh({g:.4} x⋅y + {c:.4})".format(
g=self.gamma, c=self.coef0)
g=self.gamma, c=self.coef0)

def update_model(self):
super().update_model()
Expand Down Expand Up @@ -136,8 +138,8 @@ class OWSVMClassification(OWBaseSVM):
def _add_type_box(self):
form = QtGui.QGridLayout()
self.type_box = box = gui.radioButtonsInBox(
self.controlArea, self, "svmtype", [], box="SVM Type",
orientation=form, callback=self.settings_changed)
self.controlArea, self, "svmtype", [], box="SVM Type",
orientation=form, callback=self.settings_changed)

form.addWidget(gui.appendRadioButton(box, "C-SVM", addToLayout=False),
0, 0, Qt.AlignLeft)
Expand Down
47 changes: 47 additions & 0 deletions Orange/widgets/classify/tests/test_owadaboostclassification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from PyQt4 import QtGui

from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.classify.owadaboost import OWAdaBoostClassification



class TestOWAdaBoostClassification(WidgetTest):

def setUp(self):
self.widget = self.create_widget(OWAdaBoostClassification)
self.spinners = []
self.spinners.append(self.widget.findChildren(QtGui.QSpinBox)[0])
self.spinners.append(self.widget.findChildren(QtGui.QDoubleSpinBox)[0])
self.combobox_algorithm = self.widget.findChildren(QtGui.QComboBox)[0]

def test_visible_boxes(self):
""" Check if boxes are visible """
self.assertEqual(self.spinners[0].isHidden(), False)
self.assertEqual(self.spinners[1].isHidden(), False)
self.assertEqual(self.combobox_algorithm.isHidden(), False)

def test_parameters_on_output(self):
""" Check right paramaters on output """
self.widget.apply()
learner_params = self.widget.learner.params
self.assertEqual(learner_params.get("n_estimators"), self.spinners[0].value())
self.assertEqual(learner_params.get("learning_rate"), self.spinners[1].value())
self.assertEqual(learner_params.get('algorithm'), self.combobox_algorithm.currentText())


def test_output_algorithm(self):
""" Check if right learning algorithm is on output when we change algorithm """
for index, algorithmName in enumerate(self.widget.losses):
self.combobox_algorithm.setCurrentIndex(index)
self.combobox_algorithm.activated.emit(index)
self.assertEqual(self.combobox_algorithm.currentText(), algorithmName)
self.widget.apply()
self.assertEqual(self.widget.learner.params.get("algorithm").capitalize(),
self.combobox_algorithm.currentText().capitalize())

def test_learner_on_output(self):
""" Check if learner is on output after create widget and apply """
self.widget.apply()
self.assertNotEqual(self.widget.learner, None)
53 changes: 53 additions & 0 deletions Orange/widgets/classify/tests/test_owknnclassification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from PyQt4 import QtGui

from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.classify.owknn import OWKNNLearner


class TestOwKnnClassification(WidgetTest):
def setUp(self):
self.widget = self.create_widget(OWKNNLearner)
self.combo_box = self.widget.findChildren(QtGui.QComboBox)
self.spinner = self.widget.findChildren(QtGui.QSpinBox)

def test_boxes_visible(self):
""" Check if all boxes visible """
self.assertEqual(self.combo_box[0].isHidden(), False)
self.assertEqual(self.combo_box[1].isHidden(), False)
self.assertEqual(self.spinner[0].isHidden(), False)

def test_values_on_output(self):
""" Check if all values right on output """
self.widget.apply()
learner = self.widget.learner.params
self.assertEqual(learner.get("n_neighbors"), self.spinner[0].value())
self.assertEqual(learner.get("metric").capitalize(), self.combo_box[0].currentText())
self.assertEqual(learner.get("weights").capitalize(), self.combo_box[1].currentText())

def test_selected_values_metrics(self):
""" Check right value of combobox metric is right on output """
for index, metric in enumerate(self.widget.metrics):
self.combo_box[0].activated.emit(index)
self.combo_box[0].setCurrentIndex(index)
self.assertEqual(self.combo_box[0].currentText().capitalize(), metric.capitalize())
self.widget.apply()
self.assertEqual(self.widget.learner.params.get("metric").capitalize(),
self.combo_box[0].currentText().capitalize())

def test_selected_values_weights(self):
""" Check right value of combobox metric is right on output """
for index, metric in enumerate(self.widget.weights):
self.combo_box[1].activated.emit(index)
self.combo_box[1].setCurrentIndex(index)
self.assertEqual(self.combo_box[1].currentText().capitalize(), metric.capitalize())
self.widget.apply()
self.assertEqual(self.widget.learner.params.get("weights").capitalize(),
self.combo_box[1].currentText().capitalize())

def test_learner_on_output(self):
""" Check if learner is on output after create widget and apply """
self.widget.apply()
self.assertNotEqual(self.widget.learner, None)

10 changes: 5 additions & 5 deletions Orange/widgets/classify/tests/test_owlogisticregression.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
import unittest

import bottleneck as bn

from Orange.data import Table
from Orange.statistics.util import stats
from Orange.classification import LogisticRegressionLearner
from Orange.widgets.classify.owlogisticregression import create_coef_table, OWLogisticRegression
from Orange.widgets.tests.base import GuiTest
from Orange.widgets.tests.base import WidgetTest


class LogisticRegressionTest(unittest.TestCase):
Expand All @@ -30,7 +30,7 @@ def test_coef_table_multiple(self):
len(classifier.domain.class_var.values))


class TestOWLogisticRegression(GuiTest):
class TestOWLogisticRegression(WidgetTest):
def test_data_before_apply(self):
widget = OWLogisticRegression()
widget = self.create_widget(OWLogisticRegression)
widget.set_data(Table("iris"))
107 changes: 107 additions & 0 deletions Orange/widgets/classify/tests/test_owsvmclassification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from PyQt4 import QtGui

from Orange.data import Table
from Orange.widgets.classify.owsvmclassification import OWSVMClassification
from Orange.widgets.tests.base import WidgetTest


class TestOWSVMClassification(WidgetTest):
def setUp(self):
self.widget = self.create_widget(OWSVMClassification)
self.widget.spin_boxes = self.widget.findChildren(QtGui.QDoubleSpinBox)
# max iter spin
self.widget.spin_boxes.append(self.widget.findChildren(QtGui.QSpinBox)[0])
# max iter checkbox
self.widget.max_iter_check_box = self.widget.findChildren(QtGui.QCheckBox)[0]
self.spin_boxes = self.widget.spin_boxes
self.event_data = None

def test_kernel_equation_run(self):
""" Check if right text is written for specific kernel """
for i in range(0, 4):
if self.widget.kernel_box.buttons[i].isChecked():
self.assertEqual(self.widget.kernel_eq, self.widget.kernels[i][1])

def test_kernel_equation(self):
""" Check if right text is written for specific kernel after click """
for index in range(0, 4):
self.widget.kernel_box.buttons[index].click()
self.assertEqual(self.widget.kernel_eq, self.widget.kernels[index][1])

def test_kernel_display_run(self):
""" Check if right spinner box for selected kernel are visible after widget start """
for button_pos, value in ((0, [False, False, False]),
(1, [True, True, True]),
(2, [True, False, False]),
(3, [True, True, False])):
if self.widget.kernel_box.buttons[button_pos].isChecked():
self.assertEqual([not self.spin_boxes[i].box.isHidden() for i in range(2, 5)],
value)
break

def test_kernel_display(self):
""" Check if right spinner box for selected kernel are visible after we select kernel """
for button_pos, value in ((0, [False, False, False]),
(1, [True, True, True]),
(2, [True, False, False]),
(3, [True, True, False])):
self.widget.kernel_box.buttons[button_pos].click()
self.widget.kernel_box.buttons[button_pos].isChecked()
self.assertEqual([not self.spin_boxes[i].box.isHidden() for i in range(2, 5)], value)

def test_optimization_box_visible(self):
""" Check if both spinner box is visible after starting widget """
self.assertEqual(self.spin_boxes[5].box.isHidden(), False)
self.assertEqual(self.spin_boxes[6].box.isHidden(), False)

def test_optimization_box_checked(self):
""" Check if spinner box for iteration limit is enabled or disabled """
for value in (True, False):
self.widget.max_iter_check_box.setChecked(value)
self.assertEqual(self.widget.max_iter_check_box.isChecked(), value)
self.assertEqual(self.spin_boxes[6].isEnabled(), value)

def test_type_button_checked(self):
""" Check if SVM type is selected after click """
self.widget.type_box.buttons[0].click()
self.assertEqual(self.widget.type_box.buttons[0].isChecked(), True)
self.widget.type_box.buttons[1].click()
self.assertEqual(self.widget.type_box.buttons[1].isChecked(), True)

def test_type_button_properties_visible(self):
""" Check if spinner box in SVM type are visible """
self.assertEqual(not self.spin_boxes[0].isHidden(), True)
self.assertEqual(not self.spin_boxes[1].isHidden(), True)

def test_data_before_apply(self):
""" Check if data are set """
self.widget.set_data(Table("iris")[:100])
self.widget.apply()
self.assertEqual(len(self.widget.data), 100)

def test_output_signal_learner(self):
""" Check if we have on output learner """
self.widget.kernel_box.buttons[0].click()
self.widget.set_data(Table("iris")[:100])
self.widget.apply()
self.assertNotEqual(self.widget.learner, None)

def test_output_params(self):
""" Check ouput params """
self.widget.kernel_box.buttons[0].click()
self.widget.set_data(Table("iris")[:100])
self.widget.max_iter_check_box.setChecked(True)
self.widget.apply()
self.widget.type_box.buttons[0].click()
params = self.widget.learner.params
self.assertEqual(params.get('C'), self.spin_boxes[0].value())
self.widget.type_box.buttons[1].click()
params = self.widget.learner.params
self.assertEqual(params.get('nu'), self.spin_boxes[1].value())
self.assertEqual(params.get('gamma'), self.spin_boxes[2].value())
self.assertEqual(params.get('coef0'), self.spin_boxes[3].value())
self.assertEqual(params.get('degree'), self.spin_boxes[4].value())
self.assertEqual(params.get('tol'), self.spin_boxes[5].value())
self.assertEqual(params.get('max_iter'), self.spin_boxes[6].value())
Loading

0 comments on commit ee78a7e

Please sign in to comment.