Skip to content

Commit 9681548

Browse files
committed
Add tests
1 parent b72823e commit 9681548

File tree

11 files changed

+364
-0
lines changed

11 files changed

+364
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
/dist
33
/MANIFEST
44
/*.egg-info
5+
/openslide/_convert*.so
56
*.pyc

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
include *.txt
22
recursive-include doc *.py *.rst
33
recursive-include examples *.html *.js *.png *.py
4+
recursive-include tests *.png *.py *.tiff

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
],
2222
),
2323
},
24+
test_suite='tests',
2425
maintainer='OpenSlide project',
2526
maintainer_email='[email protected]',
2627
description='Python interface to OpenSlide',

tests/__init__.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
# openslide-python - Python bindings for the OpenSlide library
3+
#
4+
# Copyright (c) 2016 Benjamin Gilbert
5+
#
6+
# This library is free software; you can redistribute it and/or modify it
7+
# under the terms of version 2.1 of the GNU Lesser General Public License
8+
# as published by the Free Software Foundation.
9+
#
10+
# This library is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with this library; if not, write to the Free Software Foundation,
17+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
#
19+
20+
import os
21+
22+
def file_path(name):
23+
return os.path.join(os.path.dirname(__file__), name)

tests/boxes.png

204 Bytes
Loading

tests/boxes.tiff

3.5 KB
Binary file not shown.

tests/test_base.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#
2+
# openslide-python - Python bindings for the OpenSlide library
3+
#
4+
# Copyright (c) 2016 Benjamin Gilbert
5+
#
6+
# This library is free software; you can redistribute it and/or modify it
7+
# under the terms of version 2.1 of the GNU Lesser General Public License
8+
# as published by the Free Software Foundation.
9+
#
10+
# This library is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with this library; if not, write to the Free Software Foundation,
17+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
#
19+
20+
import openslide
21+
from openslide import open_slide, OpenSlide, ImageSlide
22+
import sys
23+
import unittest
24+
25+
from . import file_path
26+
27+
# Tests should be written to be compatible with Python 2.6 unittest.
28+
29+
class TestLibrary(unittest.TestCase):
30+
def test_version(self):
31+
string = unicode if sys.version[0] == '2' else str
32+
self.assertTrue(isinstance(openslide.__version__, string))
33+
self.assertTrue(isinstance(openslide.__library_version__, string))
34+
35+
def test_open_slide(self):
36+
self.assertTrue(isinstance(open_slide(file_path('boxes.tiff')),
37+
OpenSlide))
38+
self.assertTrue(isinstance(open_slide(file_path('boxes.png')),
39+
ImageSlide))

tests/test_deepzoom.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#
2+
# openslide-python - Python bindings for the OpenSlide library
3+
#
4+
# Copyright (c) 2016 Benjamin Gilbert
5+
#
6+
# This library is free software; you can redistribute it and/or modify it
7+
# under the terms of version 2.1 of the GNU Lesser General Public License
8+
# as published by the Free Software Foundation.
9+
#
10+
# This library is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with this library; if not, write to the Free Software Foundation,
17+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
#
19+
20+
from openslide import OpenSlide, ImageSlide
21+
from openslide.deepzoom import DeepZoomGenerator
22+
import unittest
23+
24+
from . import file_path
25+
26+
# Tests should be written to be compatible with Python 2.6 unittest.
27+
28+
class _BoxesDeepZoomTest(object):
29+
def setUp(self):
30+
self.osr = self.CLASS(file_path(self.FILENAME))
31+
self.dz = DeepZoomGenerator(self.osr, 254, 1)
32+
33+
def tearDown(self):
34+
self.osr.close()
35+
36+
def test_metadata(self):
37+
self.assertEqual(self.dz.level_count, 10)
38+
self.assertEqual(self.dz.tile_count, 11)
39+
self.assertEqual(self.dz.level_tiles,
40+
((1, 1), (1, 1), (1, 1), (1, 1), (1, 1),
41+
(1, 1), (1, 1), (1, 1), (1, 1), (2, 1)))
42+
self.assertEqual(self.dz.level_dimensions,
43+
((1, 1), (2, 1), (3, 2), (5, 4), (10, 8),
44+
(19, 16), (38, 32), (75, 63), (150, 125), (300, 250)))
45+
46+
def test_get_tile(self):
47+
self.assertEqual(self.dz.get_tile(9, (1, 0)).size, (47, 250))
48+
49+
def test_get_tile_bad_level(self):
50+
self.assertRaises(ValueError, lambda: self.dz.get_tile(-1, (0, 0)))
51+
self.assertRaises(ValueError, lambda: self.dz.get_tile(10, (0, 0)))
52+
53+
def test_get_tile_bad_address(self):
54+
self.assertRaises(ValueError, lambda: self.dz.get_tile(0, (-1, 0)))
55+
self.assertRaises(ValueError, lambda: self.dz.get_tile(0, (1, 0)))
56+
57+
def test_get_tile_coordinates(self):
58+
self.assertEqual(self.dz.get_tile_coordinates(9, (1, 0)),
59+
((253, 0), 0, (47, 250)))
60+
61+
def test_get_tile_dimensions(self):
62+
self.assertEqual(self.dz.get_tile_dimensions(9, (1, 0)), (47, 250))
63+
64+
def test_get_dzi(self):
65+
self.assertTrue('http://schemas.microsoft.com/deepzoom/2008' in
66+
self.dz.get_dzi('jpeg'))
67+
68+
69+
class TestSlideDeepZoom(_BoxesDeepZoomTest, unittest.TestCase):
70+
CLASS = OpenSlide
71+
FILENAME = 'boxes.tiff'
72+
73+
74+
class TestImageDeepZoom(_BoxesDeepZoomTest, unittest.TestCase):
75+
CLASS = ImageSlide
76+
FILENAME = 'boxes.png'

tests/test_imageslide.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#
2+
# openslide-python - Python bindings for the OpenSlide library
3+
#
4+
# Copyright (c) 2016 Benjamin Gilbert
5+
#
6+
# This library is free software; you can redistribute it and/or modify it
7+
# under the terms of version 2.1 of the GNU Lesser General Public License
8+
# as published by the Free Software Foundation.
9+
#
10+
# This library is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with this library; if not, write to the Free Software Foundation,
17+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
#
19+
20+
from openslide import ImageSlide, OpenSlideError
21+
from PIL import Image
22+
import unittest
23+
24+
from . import file_path
25+
26+
# Tests should be written to be compatible with Python 2.6 unittest.
27+
28+
class TestImageWithoutOpening(unittest.TestCase):
29+
def test_detect_format(self):
30+
self.assertTrue(
31+
ImageSlide.detect_format(file_path('__missing_file')) is None)
32+
self.assertTrue(
33+
ImageSlide.detect_format(file_path('../setup.py')) is None)
34+
self.assertEqual(
35+
ImageSlide.detect_format(file_path('boxes.png')), 'PNG')
36+
37+
def test_open(self):
38+
self.assertRaises(IOError,
39+
lambda: ImageSlide(file_path('__does_not_exist')))
40+
self.assertRaises(IOError,
41+
lambda: ImageSlide(file_path('../setup.py')))
42+
43+
# passing PIL.Image to ImageSlide
44+
self.assertEqual(
45+
ImageSlide(Image.open(file_path('boxes.png'))).dimensions,
46+
(300, 250))
47+
48+
def test_operations_on_closed_handle(self):
49+
img = Image.open(file_path('boxes.png'))
50+
osr = ImageSlide(img)
51+
osr.close()
52+
self.assertRaises(AttributeError,
53+
lambda: osr.read_region((0, 0), 0, (100, 100)))
54+
# If an Image is passed to the constructor, ImageSlide.close()
55+
# shouldn't close it
56+
self.assertEqual(img.getpixel((0, 0)), 3)
57+
58+
def test_context_manager(self):
59+
osr = ImageSlide(file_path('boxes.png'))
60+
with osr:
61+
pass
62+
self.assertRaises(AttributeError,
63+
lambda: osr.read_region((0, 0), 0, (100, 100)))
64+
65+
66+
class TestImage(unittest.TestCase):
67+
def setUp(self):
68+
self.osr = ImageSlide(file_path('boxes.png'))
69+
70+
def tearDown(self):
71+
self.osr.close()
72+
73+
def test_metadata(self):
74+
self.assertEqual(self.osr.level_count, 1)
75+
self.assertEqual(self.osr.level_dimensions, ((300, 250),))
76+
self.assertEqual(self.osr.dimensions, (300, 250))
77+
self.assertEqual(self.osr.level_downsamples, (1.0,))
78+
79+
self.assertEqual(self.osr.get_best_level_for_downsample(0.5), 0)
80+
self.assertEqual(self.osr.get_best_level_for_downsample(3), 0)
81+
82+
self.assertEqual(self.osr.properties, {})
83+
self.assertEqual(self.osr.associated_images, {})
84+
85+
def test_read_region(self):
86+
self.assertEqual(self.osr.read_region((-10, -10), 0, (400, 400)).size,
87+
(400, 400))
88+
89+
def test_read_region_size_dimension_zero(self):
90+
self.assertEqual(self.osr.read_region((0, 0), 0, (400, 0)).size,
91+
(400, 0))
92+
93+
def test_read_region_bad_level(self):
94+
self.assertRaises(OpenSlideError,
95+
lambda: self.osr.read_region((0, 0), 1, (100, 100)))
96+
97+
def test_read_region_bad_size(self):
98+
self.assertRaises(OpenSlideError,
99+
lambda: self.osr.read_region((0, 0), 0, (400, -5)))
100+
101+
def test_thumbnail(self):
102+
self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83))

tests/test_openslide.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#
2+
# openslide-python - Python bindings for the OpenSlide library
3+
#
4+
# Copyright (c) 2016 Benjamin Gilbert
5+
#
6+
# This library is free software; you can redistribute it and/or modify it
7+
# under the terms of version 2.1 of the GNU Lesser General Public License
8+
# as published by the Free Software Foundation.
9+
#
10+
# This library is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12+
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13+
# License for more details.
14+
#
15+
# You should have received a copy of the GNU Lesser General Public License
16+
# along with this library; if not, write to the Free Software Foundation,
17+
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18+
#
19+
20+
from ctypes import ArgumentError
21+
from openslide import (OpenSlide, OpenSlideError,
22+
OpenSlideUnsupportedFormatError)
23+
import unittest
24+
25+
from . import file_path
26+
27+
# Tests should be written to be compatible with Python 2.6 unittest.
28+
29+
class TestSlideWithoutOpening(unittest.TestCase):
30+
def test_detect_format(self):
31+
self.assertTrue(
32+
OpenSlide.detect_format(file_path('__missing_file')) is None)
33+
self.assertTrue(
34+
OpenSlide.detect_format(file_path('../setup.py')) is None)
35+
self.assertEqual(
36+
OpenSlide.detect_format(file_path('boxes.tiff')),
37+
'generic-tiff')
38+
39+
def test_open(self):
40+
self.assertRaises(OpenSlideUnsupportedFormatError,
41+
lambda: OpenSlide('__does_not_exist'))
42+
self.assertRaises(OpenSlideUnsupportedFormatError,
43+
lambda: OpenSlide('setup.py'))
44+
self.assertRaises(OpenSlideError,
45+
lambda: OpenSlide('unopenable.tiff'))
46+
47+
def test_operations_on_closed_handle(self):
48+
osr = OpenSlide(file_path('boxes.tiff'))
49+
props = osr.properties
50+
associated = osr.associated_images
51+
osr.close()
52+
self.assertRaises(ArgumentError,
53+
lambda: osr.read_region((0, 0), 0, (100, 100)))
54+
self.assertRaises(ArgumentError, lambda: osr.close())
55+
self.assertRaises(ArgumentError, lambda: props['openslide.vendor'])
56+
self.assertRaises(ArgumentError, lambda: associated['label'])
57+
58+
def test_context_manager(self):
59+
osr = OpenSlide(file_path('boxes.tiff'))
60+
with osr:
61+
self.assertEqual(osr.level_count, 4)
62+
self.assertRaises(ArgumentError, lambda: osr.level_count)
63+
64+
65+
class TestSlide(unittest.TestCase):
66+
def setUp(self):
67+
self.osr = OpenSlide(file_path('boxes.tiff'))
68+
69+
def tearDown(self):
70+
self.osr.close()
71+
72+
def test_basic_metadata(self):
73+
self.assertEqual(self.osr.level_count, 4)
74+
self.assertEqual(self.osr.level_dimensions,
75+
((300, 250), (150, 125), (75, 62), (37, 31)))
76+
self.assertEqual(self.osr.dimensions, (300, 250))
77+
78+
self.assertEqual(len(self.osr.level_downsamples), self.osr.level_count)
79+
self.assertEqual(self.osr.level_downsamples[0:2], (1, 2))
80+
self.assertAlmostEqual(self.osr.level_downsamples[2], 4, places=0)
81+
self.assertAlmostEqual(self.osr.level_downsamples[3], 8, places=0)
82+
83+
self.assertEqual(self.osr.get_best_level_for_downsample(0.5), 0)
84+
self.assertEqual(self.osr.get_best_level_for_downsample(3), 1)
85+
self.assertEqual(self.osr.get_best_level_for_downsample(37), 3)
86+
87+
def test_properties(self):
88+
self.assertEqual(self.osr.properties['openslide.vendor'],
89+
'generic-tiff')
90+
self.assertRaises(KeyError,
91+
lambda: self.osr.properties['__does_not_exist'])
92+
# test __len__ and __iter__
93+
self.assertEqual(len([v for v in self.osr.properties]),
94+
len(self.osr.properties))
95+
96+
def test_associated_images(self):
97+
# XXX test an associated image
98+
self.assertRaises(KeyError,
99+
lambda: self.osr.associated_images['__missing'])
100+
# test __len__ and __iter__
101+
self.assertEqual(len([v for v in self.osr.associated_images]),
102+
len(self.osr.associated_images))
103+
104+
def test_read_region(self):
105+
self.assertEqual(self.osr.read_region((-10, -10), 1, (400, 400)).size,
106+
(400, 400))
107+
108+
def test_read_region_size_dimension_zero(self):
109+
self.assertEqual(self.osr.read_region((0, 0), 1, (400, 0)).size,
110+
(400, 0))
111+
112+
def test_read_region_bad_level(self):
113+
self.assertEqual(self.osr.read_region((0, 0), 4, (100, 100)).size,
114+
(100, 100))
115+
116+
def test_read_region_bad_size(self):
117+
self.assertRaises(OpenSlideError,
118+
lambda: self.osr.read_region((0, 0), 1, (400, -5)))
119+
120+
def test_thumbnail(self):
121+
self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83))

0 commit comments

Comments
 (0)