-
Notifications
You must be signed in to change notification settings - Fork 98
Improve tests for AbstractDataSource subclasses #244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3714bd5
d9ba227
8bfa702
6edd34e
262c2bc
ffa0e9e
5e16075
bee330b
e7c0551
1f182e2
ddd8c40
6eeb229
2d90823
530f2bb
0479ba4
b7f87fb
60aed7c
93772da
9897383
f25cb9f
bfb0883
2b25fda
d743dd9
bc02978
6ba47ec
1a998ed
d734ef3
99bea26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,49 +1,148 @@ | ||
| """ | ||
| Test of basic dataseries behavior. | ||
| Tests of ArrayDataSource behavior. | ||
| """ | ||
|
|
||
| import unittest | ||
| import pickle | ||
|
|
||
| from numpy import arange, array, allclose, empty, isnan, nan | ||
| import unittest2 as unittest | ||
| from numpy import arange, array, allclose, empty, isnan, nan, ones | ||
| from numpy.testing import assert_array_equal | ||
| import numpy as np | ||
|
|
||
| from chaco.api import ArrayDataSource, PointDataSource | ||
| from traits.testing.unittest_tools import UnittestTools | ||
|
|
||
|
|
||
| class ArrayDataTestCase(unittest.TestCase): | ||
| def test_basic_set_get(self): | ||
| myarray = arange(10) | ||
| sd = ArrayDataSource(myarray) | ||
| self.assertTrue(allclose(myarray, sd._data)) | ||
| self.assert_(sd.value_dimension == "scalar") | ||
| return | ||
| class ArrayDataSourceTestCase(UnittestTools, unittest.TestCase): | ||
|
|
||
| def setUp(self): | ||
| self.myarray = arange(10) | ||
| self.mymask = array([i % 2 for i in self.myarray], dtype=bool) | ||
| self.data_source = ArrayDataSource(self.myarray) | ||
|
|
||
| def test_init_defaults(self): | ||
| data_source = ArrayDataSource() | ||
| assert_array_equal(data_source._data, []) | ||
| self.assertEqual(data_source.value_dimension, "scalar") | ||
| self.assertEqual(data_source.index_dimension, "scalar") | ||
| self.assertEqual(data_source.sort_order, "none") | ||
| self.assertFalse(data_source.is_masked()) | ||
| self.assertEqual(data_source.persist_data, True) | ||
|
|
||
| def test_basic_setup(self): | ||
| assert_array_equal(self.myarray, self.data_source._data) | ||
| self.assertEqual(self.data_source.value_dimension, "scalar") | ||
| self.assertEqual(self.data_source.sort_order, "none") | ||
| self.assertFalse(self.data_source.is_masked()) | ||
|
|
||
| def test_set_data(self): | ||
| new_array = arange(0, 20, 2) | ||
|
|
||
| with self.assertTraitChanges(self.data_source, 'data_changed', | ||
| count=1): | ||
| self.data_source.set_data(new_array) | ||
|
|
||
| assert_array_equal(new_array, self.data_source._data) | ||
| self.assertEqual(self.data_source.get_bounds(), (0, 18)) | ||
| self.assertEqual(self.data_source.sort_order, "none") | ||
|
|
||
| def test_set_data_ordered(self): | ||
| new_array = arange(20, 0, -2) | ||
|
|
||
| with self.assertTraitChanges(self.data_source, 'data_changed', | ||
| count=1): | ||
| self.data_source.set_data(new_array, sort_order='descending') | ||
|
|
||
| assert_array_equal(new_array, self.data_source._data) | ||
| self.assertEqual(self.data_source.get_bounds(), (2, 20)) | ||
| self.assertEqual(self.data_source.sort_order, "descending") | ||
|
|
||
| def test_set_mask(self): | ||
| with self.assertTraitChanges(self.data_source, 'data_changed', | ||
| count=1): | ||
| self.data_source.set_mask(self.mymask) | ||
|
|
||
| assert_array_equal(self.myarray, self.data_source._data) | ||
| assert_array_equal(self.mymask, self.data_source._cached_mask) | ||
| self.assertTrue(self.data_source.is_masked()) | ||
| self.assertEqual(self.data_source.get_bounds(), (0, 9)) | ||
|
|
||
| def test_remove_mask(self): | ||
| self.data_source.set_mask(self.mymask) | ||
| self.assertTrue(self.data_source.is_masked()) | ||
|
|
||
| with self.assertTraitChanges(self.data_source, 'data_changed', | ||
| count=1): | ||
| self.data_source.remove_mask() | ||
|
|
||
| assert_array_equal(self.myarray, self.data_source._data) | ||
| self.assertIsNone(self.data_source._cached_mask, None) | ||
| self.assertFalse(self.data_source.is_masked()) | ||
| self.assertEqual(self.data_source.get_bounds(), (0, 9)) | ||
|
|
||
| def test_get_data(self): | ||
| assert_array_equal(self.myarray, self.data_source.get_data()) | ||
|
|
||
| def test_get_data_no_data(self): | ||
| data_source = ArrayDataSource(None) | ||
|
|
||
| assert_array_equal(data_source.get_data(), 0.0) | ||
|
|
||
| def test_get_data_mask(self): | ||
| self.data_source.set_mask(self.mymask) | ||
|
|
||
| data, mask = self.data_source.get_data_mask() | ||
| assert_array_equal(data, self.myarray) | ||
| assert_array_equal(mask, self.mymask) | ||
|
|
||
| @unittest.skip('get_data_mask() fails in this case') | ||
| def test_get_data_mask_no_data(self): | ||
| data_source = ArrayDataSource(None) | ||
|
|
||
| data, mask = data_source.get_data_mask() | ||
| assert_array_equal(data, 0.0) | ||
| assert_array_equal(mask, True) | ||
|
|
||
| def test_get_data_mask_no_mask(self): | ||
| data, mask = self.data_source.get_data_mask() | ||
| assert_array_equal(data, self.myarray) | ||
| assert_array_equal(mask, ones(shape=10, dtype=bool)) | ||
|
|
||
| def test_bounds(self): | ||
| # ascending | ||
| myarray = arange(10) | ||
| sd = ArrayDataSource(myarray, sort_order="ascending") | ||
| bounds = sd.get_bounds() | ||
| self.assert_(bounds == (0,9)) | ||
| bounds = self.data_source.get_bounds() | ||
| self.assertEqual(bounds, (0, 9)) | ||
|
|
||
| # descending | ||
| myarray = arange(10)[::-1] | ||
| sd = ArrayDataSource(myarray, sort_order="descending") | ||
| bounds = sd.get_bounds() | ||
| self.assert_(bounds == (0,9)) | ||
| data_source = ArrayDataSource(myarray, sort_order="descending") | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (0, 9)) | ||
|
|
||
| # no order | ||
| myarray = array([12,3,0,9,2,18,3]) | ||
| sd = ArrayDataSource(myarray, sort_order="none") | ||
| bounds = sd.get_bounds() | ||
| self.assert_(bounds == (0,18)) | ||
| return | ||
| myarray = array([12, 3, 0, 9, 2, 18, 3]) | ||
| data_source = ArrayDataSource(myarray, sort_order="none") | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (0, 18)) | ||
|
|
||
| def test_data_size(self): | ||
| # We know that ScalarData always returns the exact length of its data | ||
| myarray = arange(913) | ||
| sd = ArrayDataSource(myarray) | ||
| self.assert_(len(myarray) == sd.get_size()) | ||
| return | ||
| def test_bounds_length_one(self): | ||
| # this is special-cased in the code, so exercise the code path | ||
| data_source = ArrayDataSource(array([1.0])) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (1.0, 1.0)) | ||
|
|
||
| def test_bounds_length_zero(self): | ||
| # this is special-cased in the code, so exercise the code path | ||
| data_source = ArrayDataSource(array([])) | ||
| bounds = data_source.get_bounds() | ||
| # XXX this is sort of inconsistent with test_bounds_all_nans() | ||
| self.assertEqual(bounds, (0, 0)) | ||
|
|
||
| def test_bounds_empty(self): | ||
| data_source = ArrayDataSource() | ||
| bounds = data_source.get_bounds() | ||
| # XXX this is sort of inconsistent with test_bounds_all_nans() | ||
| self.assertEqual(bounds, (0, 0)) | ||
|
|
||
| def test_bounds_all_nans(self): | ||
| myarray = empty(10) | ||
|
|
@@ -53,12 +152,108 @@ def test_bounds_all_nans(self): | |
| self.assertTrue(isnan(bounds[0])) | ||
| self.assertTrue(isnan(bounds[1])) | ||
|
|
||
| def test_bounds_some_nan(self): | ||
| data_source = ArrayDataSource(array([np.nan, 3, 0, 9, np.nan, 18, 3])) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (0, 18)) | ||
|
|
||
| def test_bounds_negative_inf(self): | ||
| data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, 18, 3])) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (-np.inf, 18)) | ||
|
|
||
| def test_bounds_positive_inf(self): | ||
| data_source = ArrayDataSource(array([12, 3, 0, 9, 2, np.inf, 3])) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (0, np.inf)) | ||
|
|
||
| def test_bounds_negative_positive_inf(self): | ||
| data_source = ArrayDataSource(array([12, 3, -np.inf, 9, 2, np.inf, 3])) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (-np.inf, np.inf)) | ||
|
|
||
| def test_bounds_non_numeric(self): | ||
| myarray = np.array([u'abc', u'foo', u'bar', u'def'], dtype=unicode) | ||
| sd = ArrayDataSource(myarray) | ||
| bounds = sd.get_bounds() | ||
| data_source = ArrayDataSource(myarray) | ||
| bounds = data_source.get_bounds() | ||
| self.assertEqual(bounds, (u'abc', u'def')) | ||
|
|
||
| def test_data_size(self): | ||
| # We know that ArrayDataTestCase always returns the exact length of | ||
| # its data | ||
| myarray = arange(913) | ||
| data_source = ArrayDataSource(myarray) | ||
| self.assertEqual(len(myarray), data_source.get_size()) | ||
|
|
||
| def test_reverse_map(self): | ||
| # sort_order ascending | ||
| myarray = arange(10) | ||
| data_source = ArrayDataSource(myarray, sort_order='ascending') | ||
|
|
||
| self.assertEqual(data_source.reverse_map(4.0), 4) | ||
|
|
||
| # sort_order descending | ||
| myarray = arange(10)[::-1] | ||
| data_source = ArrayDataSource(myarray, sort_order='descending') | ||
|
|
||
| self.assertEqual(data_source.reverse_map(4.0), 5) | ||
|
|
||
| # sort_order none | ||
| myarray = array([12, 3, 0, 9, 2, 18, 3]) | ||
| data_source = ArrayDataSource(myarray, sort_order='none') | ||
|
|
||
| with self.assertRaises(NotImplementedError): | ||
| data_source.reverse_map(3) | ||
|
|
||
| def test_metadata(self): | ||
| self.assertEqual(self.data_source.metadata, | ||
| {'annotations': [], 'selections': []}) | ||
|
|
||
| def test_metadata_changed(self): | ||
| with self.assertTraitChanges(self.data_source, 'metadata_changed', | ||
| count=1): | ||
| self.data_source.metadata = {'new_metadata': True} | ||
|
|
||
| def test_metadata_items_changed(self): | ||
| with self.assertTraitChanges(self.data_source, 'metadata_changed', | ||
| count=1): | ||
| self.data_source.metadata['new_metadata'] = True | ||
|
|
||
| def test_serialization_state(self): | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to add a test that calls
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We already have that, but it is skipped because of brokenness with the super calls: https://github.com/enthought/chaco/blob/enh/data-source-tests/chaco/tests/arraydatasource_test_case.py#L252 |
||
| state = self.data_source.__getstate__() | ||
| self.assertNotIn('value_dimension', state) | ||
| self.assertNotIn('index_dimension', state) | ||
| self.assertNotIn('persist_data', state) | ||
|
|
||
| @unittest.skip("persist_data probably shouldn't be persisted") | ||
| def test_serialization_state_no_persist(self): | ||
| self.data_source.persist_data = False | ||
|
|
||
| state = self.data_source.__getstate__() | ||
| self.assertNotIn('value_dimension', state) | ||
| self.assertNotIn('index_dimension', state) | ||
| self.assertNotIn('persist_data', state) | ||
| for key in ["_data", "_cached_mask", "_cached_bounds", "_min_index", | ||
| "_max_index"]: | ||
| self.assertIn(key, state) | ||
|
|
||
| @unittest.skip("I think this is just broken") | ||
| def test_serialization_post_load(self): | ||
| self.data_source.set_mask(self.mymask) | ||
|
|
||
| pickled_data_source = pickle.dumps(self.data_source) | ||
| unpickled_data_source = pickle.loads(pickled_data_source) | ||
| unpickled_data_source._post_load() | ||
|
|
||
| self.assertEqual(unpickled_data_source._cached_bounds, ()) | ||
| self.assertEqual(unpickled_data_source._cached_mask, None) | ||
|
|
||
| assert_array_equal(self.data_source.get_data(), | ||
| unpickled_data_source.get_data()) | ||
|
|
||
| mask = unpickled_data_source.get_data_mask()[1] | ||
| assert_array_equal(mask, ones(10)) | ||
|
|
||
|
|
||
| class PointDataTestCase(unittest.TestCase): | ||
| # Since PointData is mostly the same as ScalarData, the key things to | ||
|
|
@@ -69,16 +264,17 @@ def create_array(self): | |
| def test_basic_set_get(self): | ||
| myarray = self.create_array() | ||
| pd = PointDataSource(myarray) | ||
| self.assertTrue(allclose(myarray,pd._data)) | ||
| self.assertTrue(allclose(myarray, pd._data)) | ||
| self.assert_(pd.value_dimension == "point") | ||
| return | ||
|
|
||
| def test_bounds(self): | ||
| myarray = self.create_array() | ||
| pd = PointDataSource(myarray) | ||
| self.assertEqual(pd.get_bounds(),((0,0), (9,90))) | ||
| self.assertEqual(pd.get_bounds(), ((0, 0), (9, 90))) | ||
| return | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| import nose | ||
| nose.run() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| PngSuite | ||
| -------- | ||
|
|
||
| Permission to use, copy, modify and distribute these images for any | ||
| purpose and without fee is hereby granted. | ||
|
|
||
|
|
||
| (c) Willem van Schaik, 1996, 2011 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are missing a few defaults:
metadata,persist_data,index_dimension. Any reason not to add them?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Metadata is tested in its own unit test. I'll add the others.