Skip to content

Commit 329a9cb

Browse files
authored
Merge pull request #1472 from kernc/enable-test-report
Enable report testing
2 parents 4682941 + a21a587 commit 329a9cb

File tree

4 files changed

+58
-74
lines changed

4 files changed

+58
-74
lines changed
Lines changed: 45 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import unittest
1+
from importlib import import_module
2+
import os
3+
import warnings
4+
25
from PyQt4.QtGui import QFont, QBrush
36
from PyQt4.QtCore import Qt
47
from Orange.data.table import Table
@@ -9,43 +12,15 @@
912
from Orange.distance import Euclidean
1013
from Orange.canvas.report.owreport import OWReport
1114
from Orange.widgets import gui
15+
from Orange.widgets.widget import OWWidget
1216
from Orange.widgets.tests.base import WidgetTest
13-
from Orange.widgets.classify.owclassificationtree import OWClassificationTree
1417
from Orange.widgets.classify.owclassificationtreegraph import OWClassificationTreeGraph
15-
from Orange.widgets.classify.owknn import OWKNNLearner
16-
from Orange.widgets.classify.owlogisticregression import OWLogisticRegression
17-
from Orange.widgets.classify.owmajority import OWMajority
18-
from Orange.widgets.classify.ownaivebayes import OWNaiveBayes
19-
from Orange.widgets.classify.owrandomforest import OWRandomForest
20-
from Orange.widgets.classify.owsvmclassification import OWSVMClassification
21-
from Orange.widgets.data.owconcatenate import OWConcatenate
22-
from Orange.widgets.data.owcontinuize import OWContinuize
23-
from Orange.widgets.data.owdatainfo import OWDataInfo
24-
from Orange.widgets.data.owdatasampler import OWDataSampler
25-
from Orange.widgets.data.owdiscretize import OWDiscretize
26-
from Orange.widgets.data.owfeatureconstructor import OWFeatureConstructor
2718
from Orange.widgets.data.owfile import OWFile
28-
from Orange.widgets.data.owimpute import OWImpute
29-
from Orange.widgets.data.owmergedata import OWMergeData
30-
from Orange.widgets.data.owoutliers import OWOutliers
31-
from Orange.widgets.data.owpaintdata import OWPaintData
32-
from Orange.widgets.data.owpurgedomain import OWPurgeDomain
33-
from Orange.widgets.data.owrank import OWRank
34-
from Orange.widgets.data.owselectcolumns import OWSelectAttributes
35-
from Orange.widgets.data.owselectrows import OWSelectRows
36-
from Orange.widgets.data.owsql import OWSql
37-
from Orange.widgets.data.owtable import OWDataTable
38-
from Orange.widgets.data.owcolor import OWColor
39-
from Orange.widgets.data.owpreprocess import OWPreprocess
4019
from Orange.widgets.evaluate.owcalibrationplot import OWCalibrationPlot
4120
from Orange.widgets.evaluate.owliftcurve import OWLiftCurve
4221
from Orange.widgets.evaluate.owrocanalysis import OWROCAnalysis
4322
from Orange.widgets.evaluate.owtestlearners import OWTestLearners
44-
from Orange.widgets.regression.owregressiontree import OWRegressionTree
4523
from Orange.widgets.regression.owregressiontreegraph import OWRegressionTreeGraph
46-
from Orange.widgets.regression.owknnregression import OWKNNRegression
47-
from Orange.widgets.regression.owmean import OWMean
48-
from Orange.widgets.regression.owsvmregression import OWSVMRegression
4924
from Orange.widgets.unsupervised.owcorrespondence import OWCorrespondenceAnalysis
5025
from Orange.widgets.unsupervised.owdistancemap import OWDistanceMap
5126
from Orange.widgets.unsupervised.owdistances import OWDistances
@@ -54,15 +29,35 @@
5429
from Orange.widgets.unsupervised.owmds import OWMDS
5530
from Orange.widgets.unsupervised.owpca import OWPCA
5631
from Orange.widgets.utils.itemmodels import PyTableModel
57-
from Orange.widgets.visualize.owboxplot import OWBoxPlot
58-
from Orange.widgets.visualize.owdistributions import OWDistributions
59-
from Orange.widgets.visualize.owheatmap import OWHeatMap
60-
from Orange.widgets.visualize.owlinearprojection import OWLinearProjection
61-
from Orange.widgets.visualize.owmosaic import OWMosaicDisplay
62-
from Orange.widgets.visualize.owscattermap import OWScatterMap
63-
from Orange.widgets.visualize.owscatterplot import OWScatterPlot
64-
from Orange.widgets.visualize.owsieve import OWSieveDiagram
65-
from Orange.widgets.visualize.owvenndiagram import OWVennDiagram
32+
33+
34+
def get_owwidgets(top_module_name):
35+
top_module = import_module(top_module_name)
36+
widgets = []
37+
for root, dirs, files in os.walk(top_module.__path__[0]):
38+
root = root[len(top_module.__path__[0]):].lstrip(os.path.sep)
39+
for file in files:
40+
if file.lower().startswith('ow') and file.lower().endswith('.py'):
41+
module_name = top_module_name + '.' + os.path.join(root, file).replace(os.path.sep, '.')[:-len('.py')]
42+
try:
43+
module = import_module(module_name, top_module_name[:top_module_name.index('.')])
44+
except ImportError:
45+
warnings.warn('Failed to import module: ' + module_name)
46+
continue
47+
for name, value in module.__dict__.items():
48+
if (name.upper().startswith('OW') and
49+
isinstance(value, type) and
50+
issubclass(value, OWWidget) and
51+
getattr(value, 'name', None) and
52+
getattr(value, 'send_report', None)):
53+
widgets.append(value)
54+
return list(set(widgets))
55+
56+
57+
DATA_WIDGETS = get_owwidgets('Orange.widgets.data')
58+
VISUALIZATION_WIDGETS = get_owwidgets('Orange.widgets.visualize')
59+
CLASSIFICATION_WIDGETS = get_owwidgets('Orange.widgets.classify')
60+
REGRESSION_WIDGETS = get_owwidgets('Orange.widgets.regression')
6661

6762

6863
class TestReport(WidgetTest):
@@ -119,57 +114,46 @@ def test_report_table(self):
119114
'</tr></table>')
120115

121116

122-
@unittest.skip('Segfaults. Dunno. @astaric says it might be something on the QWidget.')
123117
class TestReportWidgets(WidgetTest):
124-
clas_widgets = [OWClassificationTree, OWKNNLearner, OWLogisticRegression,
125-
OWMajority, OWNaiveBayes, OWRandomForest,
126-
OWSVMClassification]
127-
data_widgets = [OWConcatenate, OWContinuize, OWDataInfo, OWDataSampler,
128-
OWDiscretize, OWFeatureConstructor, OWOutliers, OWImpute,
129-
OWMergeData, OWFile, OWPaintData, OWPurgeDomain, OWRank,
130-
OWSelectAttributes, OWSelectRows, OWSql, OWDataTable,
131-
OWColor, OWPreprocess]
118+
clas_widgets = CLASSIFICATION_WIDGETS
119+
data_widgets = DATA_WIDGETS
132120
eval_widgets = [OWCalibrationPlot, OWLiftCurve, OWROCAnalysis]
133-
regr_widgets = [OWRegressionTree, OWKNNRegression, OWMean, OWSVMRegression]
121+
regr_widgets = REGRESSION_WIDGETS
134122
unsu_widgets = [OWCorrespondenceAnalysis, OWDistances, OWKMeans,
135123
OWMDS, OWPCA]
136124
dist_widgets = [OWDistanceMap, OWHierarchicalClustering]
137-
visu_widgets = [OWBoxPlot, OWDistributions, OWHeatMap, OWLinearProjection,
138-
OWMosaicDisplay, OWScatterPlot,
139-
OWSieveDiagram, OWScatterMap, OWVennDiagram]
125+
visu_widgets = VISUALIZATION_WIDGETS
140126
spec_widgets = [OWClassificationTreeGraph, OWTestLearners,
141127
OWRegressionTreeGraph]
142128

143129
def _create_report(self, widgets, rep, data):
144130
for widget in widgets:
145-
w = widget()
146-
if w.inputs and data is not None:
131+
w = self.create_widget(widget)
132+
if w.inputs and isinstance(data, w.inputs[0].type):
147133
handler = getattr(w, w.inputs[0].handler)
148134
handler(data)
149-
w.create_report_html()
135+
w.create_report_html()
150136
rep.make_report(w)
151137
# rep.show()
152138

153139
def test_report_widgets_classify(self):
154140
rep = OWReport.get_instance()
155-
data = Table("zoo")
141+
data = Table("titanic")
156142
widgets = self.clas_widgets
157143

158-
w = OWClassificationTreeGraph()
144+
w = self.create_widget(OWClassificationTreeGraph)
159145
clf = TreeLearner(max_depth=3)(data)
160146
clf.instances = data
161147
w.ctree(clf)
162148
w.create_report_html()
163149
rep.make_report(w)
164150

165-
self.assertEqual(len(widgets) + 1, 8)
166151
self._create_report(widgets, rep, data)
167152

168153
def test_report_widgets_data(self):
169154
rep = OWReport.get_instance()
170155
data = Table("zoo")
171156
widgets = self.data_widgets
172-
self.assertEqual(len(widgets), 19)
173157
self._create_report(widgets, rep, data)
174158

175159
def test_report_widgets_evaluate(self):
@@ -181,7 +165,7 @@ def test_report_widgets_evaluate(self):
181165
store_data=True)
182166
results.learner_names = ["LR l2"]
183167

184-
w = OWTestLearners()
168+
w = self.create_widget(OWTestLearners)
185169
set_learner = getattr(w, w.inputs[0].handler)
186170
set_train = getattr(w, w.inputs[1].handler)
187171
set_test = getattr(w, w.inputs[2].handler)
@@ -191,51 +175,44 @@ def test_report_widgets_evaluate(self):
191175
w.create_report_html()
192176
rep.make_report(w)
193177

194-
self.assertEqual(len(widgets) + 1, 4)
195178
self._create_report(widgets, rep, results)
196179

197180
def test_report_widgets_regression(self):
198181
rep = OWReport.get_instance()
199182
data = Table("housing")
200183
widgets = self.regr_widgets
201184

202-
w = OWRegressionTreeGraph()
185+
w = self.create_widget(OWRegressionTreeGraph)
203186
mod = TreeRegressionLearner(max_depth=3)(data)
204187
mod.instances = data
205188
w.ctree(mod)
206189
w.create_report_html()
207190
rep.make_report(w)
208191

209-
self.assertEqual(len(widgets) + 1, 5)
210192
self._create_report(widgets, rep, data)
211193

212194
def test_report_widgets_unsupervised(self):
213195
rep = OWReport.get_instance()
214196
data = Table("zoo")
215197
widgets = self.unsu_widgets
216-
self.assertEqual(len(widgets), 5)
217198
self._create_report(widgets, rep, data)
218199

219200
def test_report_widgets_unsupervised_dist(self):
220201
rep = OWReport.get_instance()
221202
data = Table("zoo")
222203
dist = Euclidean(data)
223204
widgets = self.dist_widgets
224-
self.assertEqual(len(widgets), 2)
225205
self._create_report(widgets, rep, dist)
226206

227207
def test_report_widgets_visualize(self):
228208
rep = OWReport.get_instance()
229209
data = Table("zoo")
230210
widgets = self.visu_widgets
231-
self.assertEqual(len(widgets), 9)
232211
self._create_report(widgets, rep, data)
233212

234-
@unittest.skip('... in favor of other methods. Segfaults.')
235213
def test_report_widgets_all(self):
236214
rep = OWReport.get_instance()
237215
widgets = self.clas_widgets + self.data_widgets + self.eval_widgets + \
238216
self.regr_widgets + self.unsu_widgets + self.dist_widgets + \
239217
self.visu_widgets + self.spec_widgets
240-
self.assertEqual(len(widgets), 52)
241218
self._create_report(widgets, rep, None)

Orange/widgets/data/oweditdomain.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,12 @@ def sizeHint(self):
543543
return sh.expandedTo(QSize(660, 550))
544544

545545
def send_report(self):
546-
self.report_raw("", EditDomainReport(
547-
old_domain=chain(self.data.domain.variables, self.data.domain.metas),
548-
new_domain=self.domain_model).to_html())
546+
if self.data is not None:
547+
self.report_raw("", EditDomainReport(
548+
old_domain=chain(self.data.domain.variables, self.data.domain.metas),
549+
new_domain=self.domain_model).to_html())
550+
else:
551+
self.report_data(None)
549552

550553

551554
class EditDomainReport:

Orange/widgets/unsupervised/owkmeans.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,11 @@ def set_data(self, data):
358358
self.run()
359359

360360
def send_report(self):
361+
k_clusters = self.k
362+
if self.optimize_k and self.optimization_runs and self.selected_row() is not None:
363+
k_clusters = self.optimization_runs[self.selected_row()][1].k
361364
self.report_items((
362-
("Number of clusters",
363-
self.optimization_runs[self.selected_row()][1].k
364-
if self.optimize_k else self.k),
365+
("Number of clusters", k_clusters),
365366
("Optimization",
366367
self.optimize_k != 0 and
367368
"{}, {} re-runs limited to {} steps".format(

Orange/widgets/visualize/owsilhouetteplot.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,9 @@ def commit(self):
339339
self.send("Other Data", other)
340340

341341
def send_report(self):
342+
if not len(self.cluster_var_model):
343+
return
344+
342345
self.report_plot()
343346
caption = "Silhouette plot ({} distance), clustered by '{}'".format(
344347
self.Distances[self.distance_idx][0],

0 commit comments

Comments
 (0)