source: sasview/src/sas/qtgui/Utilities/UnitTesting/GuiUtilsTest.py @ 6cb305a

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 6cb305a was 6cb305a, checked in by celinedurniak <celine.durniak@…>, 6 years ago

Fixed bugs related to plots, units, labels and data in DataExplorer? (SasView?-795, 796, 797)

  • Property mode set to 100644
File size: 20.1 KB
RevLine 
[a281ab8]1import sys
2import unittest
[f82ab8c]3import webbrowser
[a281ab8]4
[53c771e]5from PyQt5 import QtCore
6from PyQt5 import QtGui, QtWidgets
[7fb471d]7from unittest.mock import MagicMock
[1042dba]8
[31c5b58]9# set up import paths
[83eb5208]10import sas.qtgui.path_prepare
[31c5b58]11
[1042dba]12# SV imports
13from sas.sascalc.dataloader.loader import Loader
[dc5ef15]14from sas.qtgui.MainWindow.DataManager import DataManager
15from sas.qtgui.Plotting.PlotterData import Data1D
16from sas.qtgui.Plotting.PlotterData import Data2D
[1042dba]17
[a281ab8]18# Tested module
[83eb5208]19from sas.qtgui.Utilities.GuiUtils import *
[a281ab8]20
[53c771e]21if not QtWidgets.QApplication.instance():
22    app = QtWidgets.QApplication(sys.argv)
[28a84e9]23
[a281ab8]24class GuiUtilsTest(unittest.TestCase):
25    '''Test the GUI Utilities methods'''
26    def setUp(self):
27        '''Empty'''
28        pass
29
30    def tearDown(self):
[1042dba]31        '''Empty'''
[a281ab8]32        pass
33
34    def testDefaults(self):
35        """
36        Test all the global constants defined in the file.
37        """
38        # Should probably test the constants in the file,
39        # but this will done after trimming down GuiUtils
40        # and retaining only necessary variables.
41        pass
42
43    def testGetAppDir(self):
44        """
45        """
46        pass
47
48    def testGetUserDirectory(self):
49        """
50        Simple test of user directory getter
51        """
52        home_dir = os.path.expanduser("~")
53        self.assertIn(home_dir, get_user_directory())
54
55    def testCommunicate(self):
56        """
57        Test the container class with signal definitions
58        """
59        com = Communicate()
60
61        # All defined signals
62        list_of_signals = [
63            'fileReadSignal',
64            'fileDataReceivedSignal',
65            'statusBarUpdateSignal',
66            'updatePerspectiveWithDataSignal',
[f82ab8c]67            'updateModelFromPerspectiveSignal',
[e540cd2]68            'plotRequestedSignal',
69            'progressBarUpdateSignal',
[27313b7]70            'activeGraphName',
[f0bb711]71            'sendDataToPanelSignal',
[d5c5d3d]72            'updateModelFromDataOperationPanelSignal'
[a281ab8]73        ]
74
75        # Assure all signals are defined.
76        for signal in list_of_signals:
77            self.assertIn(signal, dir(com))
78
[8548d739]79    def testupdateModelItem(self):
80        """
81        Test the generic QModelItem update method
82        """
83        test_item = QtGui.QStandardItem()
84        test_list = ['aa', 4, True, ]
85        name = "Black Sabbath"
86
87        # update the item
88        updateModelItem(test_item, test_list, name)
89
90        # Make sure test_item got all data added
91        self.assertEqual(test_item.child(0).text(), name)
[53c771e]92        list_from_item = test_item.child(0).data()
[8548d739]93        self.assertIsInstance(list_from_item, list)
[53c771e]94        self.assertEqual(list_from_item[0], test_list[0])
95        self.assertEqual(list_from_item[1], test_list[1])
96        self.assertEqual(list_from_item[2], test_list[2])
[a281ab8]97
[8548d739]98    def testupdateModelItemWithPlot(self):
[a281ab8]99        """
[8548d739]100        Test the QModelItem checkbox update method
[a281ab8]101        """
[6cb305a]102        # test_item = QtGui.QStandardItem()
103        # test_list = ['aa','11']
104        # update_data = test_list
105        # name = "Black Sabbath"
106
107        # # update the item
108        # updateModelItemWithPlot(test_item, update_data, name)
109
[a281ab8]110        test_item = QtGui.QStandardItem()
[6cb305a]111        update_data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0])
[a281ab8]112        name = "Black Sabbath"
[6cb305a]113        update_data.id = '[0]data0'
114        update_data.name = 'data0'
[a281ab8]115        # update the item
[8548d739]116        updateModelItemWithPlot(test_item, update_data, name)
[6cb305a]117
[a281ab8]118        # Make sure test_item got all data added
119        self.assertEqual(test_item.child(0).text(), name)
120        self.assertTrue(test_item.child(0).isCheckable())
[6cb305a]121        data_from_item = test_item.child(0).child(0).data()
122        self.assertIsInstance(data_from_item, Data1D)
123        self.assertSequenceEqual(list(data_from_item.x), [1.0, 2.0, 3.0])
124        self.assertSequenceEqual(list(data_from_item.y), [10.0, 11.0, 12.0])
125        self.assertEqual(test_item.rowCount(), 1)
126
127        # add another dataset (different from the first one)
128        update_data1 = Data1D(x=[1.1, 2.1, 3.1], y=[10.1, 11.1, 12.1])
129        update_data1.id = '[0]data1'
130        update_data1.name = 'data1'
131        name1 = "Black Sabbath1"
132        # update the item and check number of rows
133        updateModelItemWithPlot(test_item, update_data1, name1)
134
135        self.assertEqual(test_item.rowCount(), 2)
136
137        # add another dataset (with the same name as the first one)
138        # check that number of rows was not changed but data have been updated
139        update_data2 = Data1D(x=[4.0, 5.0, 6.0], y=[13.0, 14.0, 15.0])
140        update_data2.id = '[1]data0'
141        update_data2.name = 'data0'
142        name2 = "Black Sabbath2"
143        updateModelItemWithPlot(test_item, update_data2, name2)
144        self.assertEqual(test_item.rowCount(), 2)
145
146        data_from_item = test_item.child(0).child(0).data()
147        self.assertSequenceEqual(list(data_from_item.x), [4.0, 5.0, 6.0])
148        self.assertSequenceEqual(list(data_from_item.y), [13.0, 14.0, 15.0])
[a281ab8]149
[1042dba]150
151    def testPlotsFromCheckedItems(self):
152        """
153        Test addition of a plottable to the model
154        """
155
156        # Mockup data
157        test_list0 = "FRIDAY"
158        test_list1 = "SATURDAY"
159        test_list2 = "MONDAY"
160
161        # Main item ("file")
162        checkbox_model = QtGui.QStandardItemModel()
163        checkbox_item = QtGui.QStandardItem(True)
164        checkbox_item.setCheckable(True)
165        checkbox_item.setCheckState(QtCore.Qt.Checked)
166        test_item0 = QtGui.QStandardItem()
[cee5c78]167        test_item0.setData(test_list0)
[1042dba]168
169        # Checked item 1
170        test_item1 = QtGui.QStandardItem(True)
171        test_item1.setCheckable(True)
172        test_item1.setCheckState(QtCore.Qt.Checked)
173        object_item = QtGui.QStandardItem()
[cee5c78]174        object_item.setData(test_list1)
[1042dba]175        test_item1.setChild(0, object_item)
176
177        checkbox_item.setChild(0, test_item0)
178        checkbox_item.appendRow(test_item1)
179
180        # Unchecked item 2
181        test_item2 = QtGui.QStandardItem(True)
182        test_item2.setCheckable(True)
183        test_item2.setCheckState(QtCore.Qt.Unchecked)
184        object_item = QtGui.QStandardItem()
[cee5c78]185        object_item.setData(test_list2)
[1042dba]186        test_item2.setChild(0, object_item)
187        checkbox_item.appendRow(test_item2)
188
189        checkbox_model.appendRow(checkbox_item)
190
191        # Pull out the "plottable" documents
192        plot_list = plotsFromCheckedItems(checkbox_model)
193
194        # Make sure only the checked data is present
195        # FRIDAY IN
[6cb305a]196        self.assertIn(test_list0, plot_list[1])
[1042dba]197        # SATURDAY IN
[6cb305a]198        self.assertIn(test_list1, plot_list[0])
[1042dba]199        # MONDAY NOT IN
[965fbd8]200        self.assertNotIn(test_list2, plot_list[0])
201        self.assertNotIn(test_list2, plot_list[1])
[1042dba]202
203    def testInfoFromData(self):
204        """
205        Test Info element extraction from a plottable object
206        """
207        loader = Loader()
208        manager = DataManager()
209
210        # get Data1D
211        p_file="cyl_400_20.txt"
212        output_object = loader.load(p_file)
[f4a1433]213        new_data = manager.create_gui_data(output_object[0], p_file)
[1042dba]214
215        # Extract Info elements into a model item
216        item = infoFromData(new_data)
217
218        # Test the item and its children
219        self.assertIsInstance(item, QtGui.QStandardItem)
220        self.assertEqual(item.rowCount(), 5)
221        self.assertEqual(item.text(), "Info")
222        self.assertIn(p_file,   item.child(0).text())
223        self.assertIn("Run",    item.child(1).text())
224        self.assertIn("Data1D", item.child(2).text())
225        self.assertIn(p_file,   item.child(3).text())
226        self.assertIn("Process",item.child(4).text())
227
[f82ab8c]228    def testOpenLink(self):
229        """
230        Opening a link in the external browser
231        """
232        good_url1 = r"http://test.test.com"
233        good_url2 = r"mailto:test@mail.com"
234        good_url3 = r"https://127.0.0.1"
235
236        bad_url1 = ""
237        bad_url2 = QtGui.QStandardItem()
238        bad_url3 = r"poop;//**I.am.a.!bad@url"
239
240        webbrowser.open = MagicMock()
241        openLink(good_url1)
242        openLink(good_url2)
243        openLink(good_url3)
244        self.assertEqual(webbrowser.open.call_count, 3)
245
246        with self.assertRaises(AttributeError):
247            openLink(bad_url1)
248        with self.assertRaises(AttributeError):
249            openLink(bad_url2)
250        with self.assertRaises(AttributeError):
251            openLink(bad_url3)
[1042dba]252
[28a84e9]253    def testRetrieveData1d(self):
254        """
255        """
[39551a68]256        with self.assertRaises(AttributeError):
257            retrieveData1d("BOOP")
[28a84e9]258
[9968d6a]259        #data = Data1D()
260        #with self.assertRaises(ValueError):
261        #    retrieveData1d(data)
[39551a68]262
263        data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0])
264
265        text = retrieveData1d(data)
266
267        self.assertIn("Temperature:", text)
268        self.assertIn("Beam_size:", text)
269        self.assertIn("X_min = 1.0:  X_max = 3.0", text)
270        self.assertIn("3.0 \t12.0 \t0.0 \t0.0", text)
[28a84e9]271
272    def testRetrieveData2d(self):
273        """
274        """
[39551a68]275        with self.assertRaises(AttributeError):
276            retrieveData2d("BOOP")
277        data = Data2D(image=[1.0, 2.0, 3.0],
278                      err_image=[0.01, 0.02, 0.03],
279                      qx_data=[0.1, 0.2, 0.3],
280                      qy_data=[0.1, 0.2, 0.3])
281
282        text = retrieveData2d(data)
283
284        self.assertIn("Type:         Data2D", text)
285        self.assertIn("I_min = 1.0", text)
286        self.assertIn("I_max = 3.0", text)
287        self.assertIn("2 \t0.3 \t0.3 \t3.0 \t0.03 \t0.0 \t0.0", text)
[28a84e9]288
289    def testOnTXTSave(self):
290        """
[39551a68]291        Test the file writer for saving 1d/2d data
[28a84e9]292        """
[39551a68]293        path = "test123"
294        if os.path.isfile(path):
295            os.remove(path)
296
297        # Broken data
298        data = Data1D(x=[1.0, 2.0, 3.0], y=[])
299        # Expect a raise
300        with self.assertRaises(IndexError):
301            onTXTSave(data, path)
302
303        # Good data - no dX/dY
304        data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0])
305        onTXTSave(data, path)
306
307        self.assertTrue(os.path.isfile(path))
308        with open(path,'r') as out:
309            data_read = out.read()
310            self.assertEqual("<X>   <Y>\n1  10\n2  11\n3  12\n", data_read)
311
312        if os.path.isfile(path):
313            os.remove(path)
314
315        # Good data - with dX/dY
316        data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0],
317                      dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
318
319        onTXTSave(data, path)
320        with open(path,'r') as out:
321            data_read = out.read()
322            self.assertIn("<X>   <Y>   <dY>   <dX>\n", data_read)
323            self.assertIn("1  10  0.1  0.1\n", data_read)
324            self.assertIn("2  11  0.2  0.2\n", data_read)
325            self.assertIn("3  12  0.3  0.3\n", data_read)
326
327        if os.path.isfile(path):
328            os.remove(path)
[28a84e9]329
330    def testSaveData1D(self):
331        """
[39551a68]332        Test the 1D file save method
[28a84e9]333        """
[39551a68]334        data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0],
335                      dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
336
337        # Test the .txt format
338        file_name = "test123_out.txt"
[53c771e]339        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=(file_name,''))
[39551a68]340        data.filename = "test123.txt"
341        saveData1D(data)
342        self.assertTrue(os.path.isfile(file_name))
343        os.remove(file_name)
344
345        # Test the .xml format
346        file_name = "test123_out.xml"
[53c771e]347        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=(file_name,''))
[39551a68]348        data.filename = "test123.xml"
349        saveData1D(data)
350        self.assertTrue(os.path.isfile(file_name))
351        os.remove(file_name)
352
353        # Test the wrong format
354        file_name = "test123_out.mp3"
[53c771e]355        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=(file_name,''))
[39551a68]356        data.filename = "test123.mp3"
357        saveData1D(data)
358        self.assertFalse(os.path.isfile(file_name))
[28a84e9]359
360    def testSaveData2D(self):
361        """
[39551a68]362        Test the 1D file save method
[28a84e9]363        """
[39551a68]364        data = Data2D(image=[1.0, 2.0, 3.0],
365                      err_image=[0.01, 0.02, 0.03],
366                      qx_data=[0.1, 0.2, 0.3],
367                      qy_data=[0.1, 0.2, 0.3])
368
369        # Test the .txt format
370        file_name = "test123_out.dat"
[53c771e]371        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=(file_name,''))
[39551a68]372        data.filename = "test123.dat"
373        saveData2D(data)
374        self.assertTrue(os.path.isfile(file_name))
375        os.remove(file_name)
376
377        # Test the wrong format
378        file_name = "test123_out.mp3"
[53c771e]379        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=(file_name,''))
[39551a68]380        data.filename = "test123.mp3"
381        saveData2D(data)
382        self.assertFalse(os.path.isfile(file_name))
383
[b46f285]384    def testXYTransform(self):
385        """ Assure the unit/legend transformation is correct"""
386        data = Data1D(x=[1.0, 2.0, 3.0], y=[10.0, 11.0, 12.0],
387                      dx=[0.1, 0.2, 0.3], dy=[0.1, 0.2, 0.3])
388
389        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="y")
390        self.assertEqual(xLabel, "()")
391        self.assertEqual(xscale, "linear")
392        self.assertEqual(yscale, "linear")
393
394        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x^(2)", yLabel="1/y")
395        self.assertEqual(xLabel, "^{2}(()^{2})")
396        self.assertEqual(yLabel, "1/(()^{-1})")
397        self.assertEqual(xscale, "linear")
398        self.assertEqual(yscale, "linear")
399
400        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x^(4)", yLabel="ln(y)")
401        self.assertEqual(xLabel, "^{4}(()^{4})")
402        self.assertEqual(yLabel, "\\ln{()}()")
403        self.assertEqual(xscale, "linear")
404        self.assertEqual(yscale, "linear")
405
406        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="ln(x)", yLabel="y^(2)")
407        self.assertEqual(xLabel, "\\ln{()}()")
408        self.assertEqual(yLabel, "^{2}(()^{2})")
409        self.assertEqual(xscale, "linear")
410        self.assertEqual(yscale, "linear")
411
412        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="log10(x)", yLabel="y*x^(2)")
413        self.assertEqual(xLabel, "()")
414        self.assertEqual(yLabel, " \\ \\ ^{2}(()^{2})")
415        self.assertEqual(xscale, "log")
416        self.assertEqual(yscale, "linear")
417
418        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="log10(x^(4))", yLabel="y*x^(4)")
419        self.assertEqual(xLabel, "^{4}(()^{4})")
420        self.assertEqual(yLabel, " \\ \\ ^{4}(()^{16})")
421        self.assertEqual(xscale, "log")
422        self.assertEqual(yscale, "linear")
423
424        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="1/sqrt(y)")
425        self.assertEqual(yLabel, "1/\\sqrt{}(()^{-0.5})")
426        self.assertEqual(yscale, "linear")
427
428        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="log10(y)")
429        self.assertEqual(yLabel, "()")
430        self.assertEqual(yscale, "log")
431
432        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="ln(y*x)")
433        self.assertEqual(yLabel, "\\ln{( \\ \\ )}()")
434        self.assertEqual(yscale, "linear")
435
436        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="ln(y*x^(2))")
437        self.assertEqual(yLabel, "\\ln ( \\ \\ ^{2})(()^{2})")
438        self.assertEqual(yscale, "linear")
439
440        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="ln(y*x^(4))")
441        self.assertEqual(yLabel, "\\ln ( \\ \\ ^{4})(()^{4})")
442        self.assertEqual(yscale, "linear")
443
444        xLabel, yLabel, xscale, yscale = xyTransform(data, xLabel="x", yLabel="log10(y*x^(4))")
445        self.assertEqual(yLabel, " \\ \\ ^{4}(()^{4})")
446        self.assertEqual(yscale, "log")
447
[0261bc1]448    def testParseName(self):
449        '''test parse out a string from the beinning of a string'''
450        # good input
451        value = "_test"
452        self.assertEqual(parseName(value, '_'), 'test')
453        value = "____test____"
454        self.assertEqual(parseName(value, '_'), '___test____')
455        self.assertEqual(parseName(value, '___'), '_test____')
456        self.assertEqual(parseName(value, 'test'), '____test____')
457        # bad input
458        with self.assertRaises(TypeError):
459            parseName(value, None)
460        with self.assertRaises(TypeError):
461            parseName(None, '_')
462        value = []
463        with self.assertRaises(TypeError):
464            parseName(value, '_')
465        value = 1.44
466        with self.assertRaises(TypeError):
467            parseName(value, 'p')
468        value = 100
469        with self.assertRaises(TypeError):
470            parseName(value, 'p')
471
472    def testToDouble(self):
473        '''test homemade string-> double converter'''
474        #good values
475        value = "1"
476        self.assertEqual(toDouble(value), 1.0)
477        value = "1.2"
478        # has to be AlmostEqual due to numerical rounding
479        self.assertAlmostEqual(toDouble(value), 1.2, 6)
480        value = "2,1"
481        self.assertAlmostEqual(toDouble(value), 2.1, 6)
482
483        # bad values
484        value = None
485        with self.assertRaises(TypeError):
486            toDouble(value)
487        value = "MyDouble"
488        with self.assertRaises(TypeError):
489            toDouble(value)
490        value = [1,2.2]
491        with self.assertRaises(TypeError):
492            toDouble(value)
493
494
495class DoubleValidatorTest(unittest.TestCase):
496    """ Test the validator for floats """
497    def setUp(self):
498        '''Create the validator'''
499        self.validator = DoubleValidator()
500
501    def tearDown(self):
502        '''Destroy the validator'''
503        self.validator = None
504
505    def testValidateGood(self):
506        """Test a valid float """
507        QtCore.QLocale.setDefault(QtCore.QLocale('en_US'))
508        float_good = "170"
509        self.assertEqual(self.validator.validate(float_good, 1)[0], QtGui.QValidator.Acceptable)
510        float_good = "170.11"
511        ## investigate: a double returns Invalid here!
512        ##self.assertEqual(self.validator.validate(float_good, 1)[0], QtGui.QValidator.Acceptable)
513        float_good = "17e2"
514        self.assertEqual(self.validator.validate(float_good, 1)[0], QtGui.QValidator.Acceptable)
515
516    def testValidateBad(self):
517        """Test a bad float """
518        float_bad = None
519        self.assertEqual(self.validator.validate(float_bad, 1)[0], QtGui.QValidator.Intermediate)
520        float_bad = [1]
521        with self.assertRaises(TypeError):
522           self.validator.validate(float_bad, 1)
523        float_bad = "1,3"
524        self.assertEqual(self.validator.validate(float_bad, 1)[0], QtGui.QValidator.Invalid)
525
526    def notestFixup(self):
527        """Fixup of a float"""
528        float_to_fixup = "1,3"
529        self.validator.fixup(float_to_fixup)
530        self.assertEqual(float_to_fixup, "13")
531
[d5c5d3d]532
[e4676c8]533class FormulaValidatorTest(unittest.TestCase):
534    """ Test the formula validator """
535    def setUp(self):
536        '''Create the validator'''
537        self.validator = FormulaValidator()
538
539    def tearDown(self):
540        '''Destroy the validator'''
541        self.validator = None
542
543    def testValidateGood(self):
544        """Test a valid Formula """
545        formula_good = "H24O12C4C6N2Pu"
546        self.assertEqual(self.validator.validate(formula_good, 1)[0], QtGui.QValidator.Acceptable)
547
548        formula_good = "(H2O)0.5(D2O)0.5"
549        self.assertEqual(self.validator.validate(formula_good, 1)[0], QtGui.QValidator.Acceptable)
550
551    def testValidateBad(self):
[0261bc1]552        """Test an invalid Formula """
[e4676c8]553        formula_bad = "H24 %%%O12C4C6N2Pu"
554        self.assertRaises(self.validator.validate(formula_bad, 1)[0])
555        self.assertEqual(self.validator.validate(formula_bad, 1)[0], QtGui.QValidator.Intermediate)
556
557        formula_bad = [1]
558        self.assertEqual(self.validator.validate(formula_bad, 1)[0], QtGui.QValidator.Intermediate)
559
[0261bc1]560class HashableStandardItemTest(unittest.TestCase):
561    """ Test the reimplementation of QStandardItem """
562    def setUp(self):
563        '''Create the validator'''
564        self.item = HashableStandardItem()
565
566    def tearDown(self):
567        '''Destroy the validator'''
568        self.item = None
569
570    def testHash(self):
571        '''assure the item returns hash'''
572        self.assertEqual(self.item.__hash__(), 0)
573
574    def testIndexing(self):
575        '''test that we can use HashableSI as an index'''
576        dictionary = {}
577        dictionary[self.item] = "wow!"
578        self.assertEqual(dictionary[self.item], "wow!")
579
580    def testClone(self):
581        '''let's see if we can clone the item'''
582        item_clone = self.item.clone()
583        self.assertEqual(item_clone.__hash__(), 0)
[28a84e9]584
[a281ab8]585if __name__ == "__main__":
586    unittest.main()
587
Note: See TracBrowser for help on using the repository browser.