From 920059bea13a8176d2b549655d209677dceae503 Mon Sep 17 00:00:00 2001 From: Andrew Cassidy Date: Sun, 22 May 2022 18:40:13 -0700 Subject: [PATCH] Migrate tests to pytest --- tests/test_bc1.py | 262 +++++++++++++++++++++--------------------- tests/test_bc4.py | 227 ++++++++++++++++++------------------ tests/test_install.py | 6 +- tests/test_texture.py | 66 +++++------ 4 files changed, 279 insertions(+), 282 deletions(-) diff --git a/tests/test_bc1.py b/tests/test_bc1.py index 1108c3a..4f9040f 100644 --- a/tests/test_bc1.py +++ b/tests/test_bc1.py @@ -1,208 +1,206 @@ -import unittest -from parameterized import parameterized, parameterized_class +import math + +import pytest +from PIL import Image, ImageChops + from quicktex.s3tc.bc1 import BC1Block, BC1Texture, BC1Encoder, BC1Decoder from .images import BC1Blocks -from PIL import Image, ImageChops -in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same +in_endpoints = ((253, 254, 255), (65, 70, 67)) # has some small changes that should encode the same in 5:6:5 out_endpoints = ((255, 255, 255, 255), (66, 69, 66, 255)) selectors = [[0, 2, 3, 1]] * 4 block_bytes = b'\xff\xff\x28\x42\x78\x78\x78\x78' -class TestBC1Block(unittest.TestCase): +class TestBC1Block: """Tests for the BC1Block class""" def test_size(self): """Test the size and dimensions of BC1Block""" - self.assertEqual(BC1Block.nbytes, 8, 'incorrect block size') - self.assertEqual(BC1Block.width, 4, 'incorrect block width') - self.assertEqual(BC1Block.height, 4, 'incorrect block width') - self.assertEqual(BC1Block.size, (4, 4), 'incorrect block dimensions') + assert BC1Block.nbytes == 8 + assert BC1Block.width == 4 + assert BC1Block.height == 4 + assert BC1Block.size == (4, 4) def test_buffer(self): """Test the buffer protocol of BC1Block""" block = BC1Block() mv = memoryview(block) - - self.assertFalse(mv.readonly, 'buffer is readonly') - self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') - self.assertEqual(mv.ndim, 1, 'buffer is multidimensional') - self.assertEqual(mv.nbytes, BC1Block.nbytes, 'buffer is the wrong size') - self.assertEqual(mv.format, 'B', 'buffer has the wrong format') - mv[:] = block_bytes - self.assertEqual(mv.tobytes(), block_bytes, 'incorrect buffer data') + + assert not mv.readonly + assert mv.c_contiguous + assert mv.ndim == 1 + assert mv.nbytes == 8 + assert mv.format == 'B' + assert mv.tobytes() == block_bytes + assert mv.tobytes() == block.tobytes() def test_constructor(self): """Test constructing a block out of endpoints and selectors""" block = BC1Block(*in_endpoints, selectors) - self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes') - self.assertEqual(block.selectors, selectors, 'incorrect selectors') - self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints') - self.assertFalse(block.is_3color, 'incorrect color mode') + assert block.tobytes() == block_bytes + assert block.selectors == selectors + assert block.endpoints == out_endpoints + assert not block.is_3color def test_frombytes(self): """Test constructing a block out of raw data""" block = BC1Block.frombytes(block_bytes) - self.assertEqual(block.tobytes(), block_bytes, 'incorrect block bytes') - self.assertEqual(block.selectors, selectors, 'incorrect selectors') - self.assertEqual(block.endpoints, out_endpoints, 'incorrect endpoints') - self.assertFalse(block.is_3color, 'incorrect color mode') + assert block.tobytes() == block_bytes + assert block.selectors == selectors + assert block.endpoints == out_endpoints + assert not block.is_3color def test_eq(self): """Test equality between two identical blocks""" block1 = BC1Block.frombytes(block_bytes) block2 = BC1Block.frombytes(block_bytes) - self.assertEqual(block1, block2, 'identical blocks not equal') + assert block1 == block2 -@parameterized_class( - ("name", "w", "h", "wb", "hb"), [("8x8", 8, 8, 2, 2), ("9x9", 9, 9, 3, 3), ("7x7", 7, 7, 2, 2), ("7x9", 7, 9, 2, 3)] -) -class TestBC1Texture(unittest.TestCase): - def setUp(self): - self.tex = BC1Texture(self.w, self.h) - self.nbytes = self.wb * self.hb * BC1Block.nbytes +# noinspection PyMethodMayBeStatic +@pytest.mark.parametrize('w', [7, 8, 9]) +@pytest.mark.parametrize('h', [7, 8, 9]) +class TestBC1Texture: + def test_dimensions(self, w, h): + """Test dimensions of BC1Texture in pixels, blocks, and bytes""" + tex = BC1Texture(w, h) + wb = math.ceil(w / 4) + hb = math.ceil(h / 4) - def test_size(self): - """Test size of BC1Texture in bytes""" - self.assertEqual(self.tex.nbytes, self.nbytes, 'incorrect texture size') - self.assertEqual(len(self.tex.tobytes()), self.nbytes, 'incorrect texture size from tobytes') - - def test_dimensions(self): - """Test dimensions of BC1Texture in pixels""" - self.assertEqual(self.tex.width, self.w, 'incorrect texture width') - self.assertEqual(self.tex.height, self.h, 'incorrect texture height') - self.assertEqual(self.tex.size, (self.w, self.h), 'incorrect texture dimensions') - - def test_dimensions_blocks(self): - """Test dimensions of BC1Texture in blocks""" - self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks') - self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks') - self.assertEqual(self.tex.size_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks') - - def test_blocks(self): + assert tex.nbytes == BC1Block.nbytes * wb * hb # block width x block height + assert len(tex.tobytes()) == tex.nbytes + + assert tex.width == w + assert tex.height == h + assert tex.size == (w, h) + + assert tex.width_blocks == wb + assert tex.height_blocks == hb + assert tex.size_blocks == (wb, hb) + + def test_blocks(self, w, h): """Test getting and setting blocks to BC1Texture""" - blocks = [[BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)] - for x in range(self.wb): - for y in range(self.hb): - self.tex[x, y] = blocks[y][x] - - b = self.tex.tobytes() - for x in range(self.wb): - for y in range(self.hb): - index = (x + (y * self.wb)) * BC1Block.nbytes - tb = self.tex[x, y] + tex = BC1Texture(w, h) + + # generate garbage blocks with the x and y index in the first 2 bytes + blocks = [ + [BC1Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(tex.width_blocks)] + for y in range(tex.height_blocks) + ] + # assign those blocks to the texture + for x in range(tex.width_blocks): + for y in range(tex.height_blocks): + tex[x, y] = blocks[y][x] + + # get the blocks and analyze + b = tex.tobytes() + for x in range(tex.width_blocks): + for y in range(tex.height_blocks): + index = (x + (y * tex.width_blocks)) * BC1Block.nbytes + tb = tex[x, y] fb = BC1Block.frombytes(b[index : index + BC1Block.nbytes]) - self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture') - self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes') + assert tb == blocks[y][x] + assert fb == blocks[y][x] - self.assertEqual(self.tex[-1, -1], self.tex[self.wb - 1, self.hb - 1], 'incorrect negative subscripting') + def text_subscript(self, w, h): + """Test BC1Texture subscripting for blocks""" + tex = BC1Texture(w, h) - with self.assertRaises(IndexError): - _ = self.tex[self.wb, self.hb] - with self.assertRaises(IndexError): - _ = self.tex[-1 - self.wb, -1 - self.hb] + # ensure negative wraparound works + assert tex[-1, -1] == tex[tex.width_blocks - 1, tex.height_blocks - 1] - def test_buffer(self): - """Test the buffer protocol of BC1Texture""" - mv = memoryview(self.tex) + with pytest.raises(IndexError): + _ = tex[tex.width_blocks, tex.height_blocks] + with pytest.raises(IndexError): + _ = tex[-1 - tex.width_blocks, -1 - tex.height_blocks] - self.assertFalse(mv.readonly, 'buffer is readonly') - self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') - self.assertEqual(mv.nbytes, self.nbytes, 'buffer is the wrong size') - self.assertEqual(mv.format, 'B', 'buffer has the wrong format') + def test_buffer(self, w, h): + """Test the buffer protocol of BC1Texture""" + tex = BC1Texture(w, h) + mv = memoryview(tex) - data = block_bytes * self.wb * self.hb + data = block_bytes * tex.width_blocks * tex.height_blocks mv[:] = data - self.assertEqual(mv.tobytes(), data, 'incorrect buffer data') + assert not mv.readonly + assert mv.c_contiguous + assert mv.nbytes == tex.nbytes + assert mv.format == 'B' + assert mv.tobytes() == data -@parameterized_class( - ("name", "color_mode"), - [ - ("4Color", BC1Encoder.ColorMode.FourColor), - ("3Color", BC1Encoder.ColorMode.ThreeColor), - ("3Color_Black", BC1Encoder.ColorMode.ThreeColorBlack), - ], + +@pytest.mark.parametrize( + 'color_mode', + [BC1Encoder.ColorMode.FourColor, BC1Encoder.ColorMode.ThreeColor, BC1Encoder.ColorMode.ThreeColorBlack], ) -class TestBC1Encoder(unittest.TestCase): +class TestBC1Encoder: """Test BC1Encoder""" - @classmethod - def setUpClass(cls): - cls.bc1_encoder = BC1Encoder(5, cls.color_mode) - - def test_block_4color(self): + def test_block_4color(self, color_mode): """Test encoder output with 4 color greyscale test block""" - out_tex = self.bc1_encoder.encode(BC1Blocks.greyscale.texture) - - self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks') - + encoder = BC1Encoder(color_mode=color_mode) + out_tex = encoder.encode(BC1Blocks.greyscale.texture) out_block = out_tex[0, 0] - self.assertFalse(out_block.is_3color, 'returned 3color mode for greyscale test block') - self.assertEqual(out_block, BC1Blocks.greyscale.block, 'encoded block is incorrect') - - def test_block_3color(self): - """Test encoder output with 3 color test block""" - out_tex = self.bc1_encoder.encode(BC1Blocks.three_color.texture) + assert out_tex.size_blocks == (1, 1) - self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks') + assert not out_block.is_3color + assert out_block == BC1Blocks.greyscale.block + def test_block_3color(self, color_mode): + """Test encoder output with 3 color test block""" + encoder = BC1Encoder(color_mode=color_mode) + out_tex = encoder.encode(BC1Blocks.three_color.texture) out_block = out_tex[0, 0] - if self.color_mode != BC1Encoder.ColorMode.FourColor: + assert out_tex.size_blocks == (1, 1) + + if encoder.color_mode != BC1Encoder.ColorMode.FourColor: # we only care about the selectors if we are in 3 color mode - self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block') - self.assertEqual(out_block, BC1Blocks.three_color.block, 'encoded block is incorrect') + assert out_block.is_3color + assert out_block == BC1Blocks.three_color.block else: - self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode') + assert not out_block.is_3color - def test_block_3color_black(self): + def test_block_3color_black(self, color_mode): """Test encoder output with 3 color test block with black pixels""" - out_tex = self.bc1_encoder.encode(BC1Blocks.three_color_black.texture) + encoder = BC1Encoder(color_mode=color_mode) + out_tex = encoder.encode(BC1Blocks.three_color_black.texture) + out_block = out_tex[0, 0] - self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks') + assert out_tex.size_blocks == (1, 1) - out_block = out_tex[0, 0] has_black = 3 in [j for row in out_block.selectors for j in row] - if self.color_mode == BC1Encoder.ColorMode.ThreeColorBlack: + if color_mode == BC1Encoder.ColorMode.ThreeColorBlack: # we only care about the selectors if we are in 3 color black mode - self.assertTrue(out_block.is_3color, 'returned 4-color block for 3 color test block with black') - self.assertTrue(has_black, 'block does not have black pixels as expected') - self.assertEqual(out_block, BC1Blocks.three_color_black.block, "encoded block is incorrect") - elif self.color_mode == BC1Encoder.ColorMode.ThreeColor: - self.assertFalse(has_black and out_block.is_3color, 'returned 3color block with black pixels') + assert out_block.is_3color + assert has_black + assert out_block == BC1Blocks.three_color_black.block + elif color_mode == BC1Encoder.ColorMode.ThreeColor: + assert not (has_black and out_block.is_3color) else: - self.assertFalse(out_block.is_3color, 'returned 3-color block in 4-color mode') + assert not out_block.is_3color -class TestBC1Decoder(unittest.TestCase): +@pytest.mark.parametrize('texture', [BC1Blocks.greyscale, BC1Blocks.three_color, BC1Blocks.three_color_black]) +class TestBC1Decoder: """Test BC1Decoder""" - @classmethod - def setUpClass(cls): - cls.bc1_decoder = BC1Decoder() - - @parameterized.expand( - [ - ("4color", BC1Blocks.greyscale.block, BC1Blocks.greyscale.image), - ("3color", BC1Blocks.three_color.block, BC1Blocks.three_color.image), - ("3color_black", BC1Blocks.three_color_black.block, BC1Blocks.three_color_black.image), - ] - ) - def test_block(self, _, block, image): + def test_block(self, texture): """Test decoder output for a single block""" + block = texture.block + image = texture.image + decoder = BC1Decoder() in_tex = BC1Texture(4, 4) in_tex[0, 0] = block - out_tex = self.bc1_decoder.decode(in_tex) + out_tex = decoder.decode(in_tex) - self.assertEqual(out_tex.size, (4, 4), 'decoded texture has incorrect dimensions') + assert out_tex.size == (4, 4) out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes()) img_diff = ImageChops.difference(out_img, image).convert('L') img_hist = img_diff.histogram() - self.assertEqual(16, img_hist[0], 'decoded block is incorrect') + assert img_hist[0] == 16 diff --git a/tests/test_bc4.py b/tests/test_bc4.py index e5a6ad5..a78bb38 100644 --- a/tests/test_bc4.py +++ b/tests/test_bc4.py @@ -1,178 +1,179 @@ -import unittest -from parameterized import parameterized, parameterized_class +import math + +import pytest +from PIL import Image, ImageChops + from quicktex.s3tc.bc4 import BC4Block, BC4Texture, BC4Encoder, BC4Decoder from .images import BC4Blocks -from PIL import Image, ImageChops +block_bytes = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA' +selectors = [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2 +endpoints = (240, 16) -class TestBC4Block(unittest.TestCase): - """Tests for the BC1Block class""" - block_bytes = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA' - selectors = [[0, 1, 2, 3]] * 2 + [[4, 5, 6, 7]] * 2 - endpoints = (240, 16) +class TestBC4Block: + """Tests for the BC1Block class""" def test_size(self): """Test the size and dimensions of BC4Block""" - self.assertEqual(BC4Block.nbytes, 8, 'incorrect block size') - self.assertEqual(BC4Block.width, 4, 'incorrect block width') - self.assertEqual(BC4Block.height, 4, 'incorrect block width') - self.assertEqual(BC4Block.size, (4, 4), 'incorrect block dimensions') + assert BC4Block.nbytes == 8 + assert BC4Block.width == 4 + assert BC4Block.height == 4 + assert BC4Block.size == (4, 4) def test_buffer(self): """Test the buffer protocol of BC4Block""" block = BC4Block() mv = memoryview(block) + mv[:] = block_bytes - self.assertFalse(mv.readonly, 'buffer is readonly') - self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') - self.assertEqual(mv.ndim, 1, 'buffer is multidimensional') - self.assertEqual(mv.nbytes, BC4Block.nbytes, 'buffer is the wrong size') - self.assertEqual(mv.format, 'B', 'buffer has the wrong format') - - mv[:] = self.block_bytes - self.assertEqual(mv.tobytes(), self.block_bytes, 'incorrect buffer data') + assert not mv.readonly + assert mv.c_contiguous + assert mv.ndim == 1 + assert mv.nbytes == 8 + assert mv.format == 'B' + assert mv.tobytes() == block_bytes + assert mv.tobytes() == block.tobytes() def test_constructor(self): """Test constructing a block out of endpoints and selectors""" - block = BC4Block(*self.endpoints, self.selectors) - self.assertEqual(block.tobytes(), self.block_bytes, 'incorrect block bytes') - self.assertEqual(block.selectors, self.selectors, 'incorrect selectors') - self.assertEqual(block.endpoints, self.endpoints, 'incorrect endpoints') + block = BC4Block(*endpoints, selectors) + assert block.tobytes() == block_bytes + assert block.selectors == selectors + assert block.endpoints == endpoints def test_frombytes(self): """Test constructing a block out of raw data""" - block = BC4Block.frombytes(self.block_bytes) - self.assertEqual(block.tobytes(), self.block_bytes, 'incorrect block bytes') - self.assertEqual(block.selectors, self.selectors, 'incorrect selectors') - self.assertEqual(block.endpoints, self.endpoints, 'incorrect endpoints') + block = BC4Block.frombytes(block_bytes) + assert block.tobytes() == block_bytes + assert block.selectors == selectors + assert block.endpoints == endpoints def test_eq(self): """Test equality between two identical blocks""" - block1 = BC4Block.frombytes(self.block_bytes) - block2 = BC4Block.frombytes(self.block_bytes) - self.assertEqual(block1, block2, 'identical blocks not equal') + block1 = BC4Block.frombytes(block_bytes) + block2 = BC4Block.frombytes(block_bytes) + assert block1 == block2 def test_values_6(self): """Test values of a 6-value block""" block = BC4Block(8, 248, [[0] * 4] * 4) - self.assertEqual(block.values, [8, 248, 56, 104, 152, 200, 0, 255], 'incorrect values') - self.assertTrue(block.is_6value, 'incorrect is_6value') + assert block.values == [8, 248, 56, 104, 152, 200, 0, 255] + assert block.is_6value def test_values_8(self): """Test values of an 8-value block""" block = BC4Block(240, 16, [[0] * 4] * 4) - self.assertEqual(block.values, [240, 16, 208, 176, 144, 112, 80, 48], 'incorrect values') - self.assertFalse(block.is_6value, 'incorrect is_6value') + assert block.values == [240, 16, 208, 176, 144, 112, 80, 48] + assert not block.is_6value -@parameterized_class( - ("name", "w", "h", "wb", "hb"), [("8x8", 8, 8, 2, 2), ("9x9", 9, 9, 3, 3), ("7x7", 7, 7, 2, 2), ("7x9", 7, 9, 2, 3)] -) -class TestBC4Texture(unittest.TestCase): - def setUp(self): - self.tex = BC4Texture(self.w, self.h) - self.nbytes = self.wb * self.hb * BC4Block.nbytes +# noinspection PyMethodMayBeStatic +@pytest.mark.parametrize('w', [7, 8, 9]) +@pytest.mark.parametrize('h', [7, 8, 9]) +class TestBC4Texture: + def test_dimensions(self, w, h): + """Test dimensions of BC4Texture in pixels, blocks, and bytes""" + tex = BC4Texture(w, h) + wb = math.ceil(w / 4) + hb = math.ceil(h / 4) - def test_size(self): - """Test size of BC4Texture in bytes""" - self.assertEqual(self.tex.nbytes, self.nbytes, 'incorrect texture size') - self.assertEqual(len(self.tex.tobytes()), self.nbytes, 'incorrect texture size from tobytes') - - def test_dimensions(self): - """Test dimensions of BC4Texture in pixels""" - self.assertEqual(self.tex.width, self.w, 'incorrect texture width') - self.assertEqual(self.tex.height, self.h, 'incorrect texture height') - self.assertEqual(self.tex.size, (self.w, self.h), 'incorrect texture dimensions') - - def test_dimensions_blocks(self): - """Test dimensions of BC4Texture in blocks""" - self.assertEqual(self.tex.width_blocks, self.wb, 'incorrect texture width_blocks') - self.assertEqual(self.tex.height_blocks, self.hb, 'incorrect texture width_blocks') - self.assertEqual(self.tex.size_blocks, (self.wb, self.hb), 'incorrect texture dimensions_blocks') - - def test_blocks(self): + assert tex.nbytes == BC4Block.nbytes * wb * hb # block width x block height + assert len(tex.tobytes()) == tex.nbytes + + assert tex.width == w + assert tex.height == h + assert tex.size == (w, h) + + assert tex.width_blocks == wb + assert tex.height_blocks == hb + assert tex.size_blocks == (wb, hb) + + def test_blocks(self, w, h): """Test getting and setting blocks to BC4Texture""" - blocks = [[BC4Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(self.wb)] for y in range(self.hb)] - for x in range(self.wb): - for y in range(self.hb): - self.tex[x, y] = blocks[y][x] - - b = self.tex.tobytes() - for x in range(self.wb): - for y in range(self.hb): - index = (x + (y * self.wb)) * BC4Block.nbytes - tb = self.tex[x, y] + tex = BC4Texture(w, h) + + # generate garbage blocks with the x and y index in the first 2 bytes + blocks = [ + [BC4Block.frombytes(bytes([x, y] + [0] * 6)) for x in range(tex.width_blocks)] + for y in range(tex.height_blocks) + ] + # assign those blocks to the texture + for x in range(tex.width_blocks): + for y in range(tex.height_blocks): + tex[x, y] = blocks[y][x] + + # get the blocks and analyze + b = tex.tobytes() + for x in range(tex.width_blocks): + for y in range(tex.height_blocks): + index = (x + (y * tex.width_blocks)) * BC4Block.nbytes + tb = tex[x, y] fb = BC4Block.frombytes(b[index : index + BC4Block.nbytes]) - self.assertEqual(tb, blocks[y][x], 'incorrect block read from texture') - self.assertEqual(fb, blocks[y][x], 'incorrect block read from texture bytes') + assert tb == blocks[y][x] + assert fb == blocks[y][x] - self.assertEqual(self.tex[-1, -1], self.tex[self.wb - 1, self.hb - 1], 'incorrect negative subscripting') + def text_subscript(self, w, h): + """Test BC4Texture subscripting for blocks""" + tex = BC4Texture(w, h) - with self.assertRaises(IndexError): - _ = self.tex[self.wb, self.hb] - with self.assertRaises(IndexError): - _ = self.tex[-1 - self.wb, -1 - self.hb] + # ensure negative wraparound works + assert tex[-1, -1] == tex[tex.width_blocks - 1, tex.height_blocks - 1] - def test_buffer(self): - """Test the buffer protocol of BC4Texture""" - mv = memoryview(self.tex) + with pytest.raises(IndexError): + _ = tex[tex.width_blocks, tex.height_blocks] + with pytest.raises(IndexError): + _ = tex[-1 - tex.width_blocks, -1 - tex.height_blocks] - self.assertFalse(mv.readonly, 'buffer is readonly') - self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') - self.assertEqual(mv.nbytes, self.nbytes, 'buffer is the wrong size') - self.assertEqual(mv.format, 'B', 'buffer has the wrong format') + def test_buffer(self, w, h): + """Test the buffer protocol of BC1Texture""" + tex = BC4Texture(w, h) + mv = memoryview(tex) - data = b'\xF0\x10\x88\x86\x68\xAC\xCF\xFA' * self.wb * self.hb + data = block_bytes * tex.width_blocks * tex.height_blocks mv[:] = data - self.assertEqual(mv.tobytes(), data, 'incorrect buffer data') + assert not mv.readonly + assert mv.c_contiguous + assert mv.nbytes == tex.nbytes + assert mv.format == 'B' + assert mv.tobytes() == data -class TestBC4Encoder(unittest.TestCase): - """Test BC4Encoder""" - # 6-value blocks are not yet supported by the encoder so we only run one test - @classmethod - def setUpClass(cls): - cls.bc4_encoder = BC4Encoder(0) +class TestBC4Encoder: + """Test BC4Encoder""" def test_block(self): """Test encoder output with 8 value test block""" - out_tex = self.bc4_encoder.encode(BC4Blocks.eight_value.texture) - - self.assertEqual(out_tex.size_blocks, (1, 1), 'encoded texture has multiple blocks') - + encoder = BC4Encoder(0) + out_tex = encoder.encode(BC4Blocks.eight_value.texture) out_block = out_tex[0, 0] - self.assertFalse(out_block.is_6value, 'returned 6value mode') - self.assertEqual(out_block, BC4Blocks.eight_value.block, 'encoded block is incorrect') + assert out_tex.size_blocks == (1, 1) + assert not out_block.is_6value + assert out_block == BC4Blocks.eight_value.block -class TestBC4Decoder(unittest.TestCase): - """Test BC4Decoder""" - @classmethod - def setUpClass(cls): - cls.bc4_decoder = BC4Decoder(0) +@pytest.mark.parametrize('texture', [BC4Blocks.eight_value, BC4Blocks.six_value]) +class TestBC4Decoder: + """Test BC4Decoder""" - @parameterized.expand( - [ - ("8value", BC4Blocks.eight_value.block, BC4Blocks.eight_value.image), - ("6value", BC4Blocks.six_value.block, BC4Blocks.six_value.image), - ] - ) - def test_block(self, _, block, image): + def test_block(self, texture): """Test decoder output for a single block""" + block = texture.block + image = texture.image + decoder = BC4Decoder(0) in_tex = BC4Texture(4, 4) in_tex[0, 0] = block - out_tex = self.bc4_decoder.decode(in_tex) + out_tex = decoder.decode(in_tex) - self.assertEqual(out_tex.size, (4, 4), 'decoded texture has incorrect dimensions') + assert out_tex.size == (4, 4) out_img = Image.frombytes('RGBA', (4, 4), out_tex.tobytes()) img_diff = ImageChops.difference(out_img, image).convert('L') img_hist = img_diff.histogram() - self.assertEqual(16, img_hist[0], 'decoded block is incorrect') + assert img_hist[0] == 16 diff --git a/tests/test_install.py b/tests/test_install.py index 106d0e8..c78e85c 100644 --- a/tests/test_install.py +++ b/tests/test_install.py @@ -1,13 +1,9 @@ """Test if everything is installed correctly""" -import unittest -import os.path import quicktex -tests_path = os.path.dirname(os.path.realpath(__file__)) - -class TestInstall(unittest.TestCase): +class TestInstall: def test_version(self): """Test if the extension module version matches what setuptools returns""" try: diff --git a/tests/test_texture.py b/tests/test_texture.py index df4750e..4b85b92 100644 --- a/tests/test_texture.py +++ b/tests/test_texture.py @@ -1,58 +1,60 @@ -import unittest import os.path -from .images import image_path -from quicktex import RawTexture + +import pytest from PIL import Image +from quicktex import RawTexture +from .images import image_path + -class TestRawTexture(unittest.TestCase): +class TestRawTexture: boilerplate = Image.open(os.path.join(image_path, 'Boilerplate.png')) boilerplate_bytes = boilerplate.tobytes('raw', 'RGBX') width, height = boilerplate.size - size = width * height * 4 - - def setUp(self): - self.tex = RawTexture(self.width, self.height) + nbytes = width * height * 4 def test_size(self): """Test byte size and image dimensions""" - self.assertEqual(self.tex.nbytes, self.size, "incorrect texture byte size") - self.assertEqual(self.tex.width, self.width, "incorrect texture width") - self.assertEqual(self.tex.height, self.height, "incorrect texture height") - self.assertEqual(self.tex.size, (self.width, self.height), "incorrect texture dimensions") + tex = RawTexture(self.width, self.height) + assert tex.nbytes == self.nbytes + assert tex.width == self.width + assert tex.height == self.height + assert tex.size == (self.width, self.height) def test_pixels(self): """Test getting and setting pixel values""" + tex = RawTexture(self.width, self.height) color1 = (69, 13, 12, 0) # totally random color color2 = (19, 142, 93, 44) - self.tex[0, 0] = color1 - self.tex[-1, -1] = color2 - data = self.tex.tobytes() + tex[0, 0] = color1 + tex[-1, -1] = color2 + data = tex.tobytes() - self.assertEqual(self.tex[0, 0], color1) - self.assertEqual(self.tex[-1, -1], color2) - self.assertEqual(tuple(data[0:4]), color1) - self.assertEqual(tuple(data[-4:]), color2) + assert tex[0, 0] == color1 + assert tex[-1, -1] == color2 + assert tuple(data[0:4]) == color1 + assert tuple(data[-4:]) == color2 - with self.assertRaises(IndexError): - thing = self.tex[self.width, self.height] - with self.assertRaises(IndexError): - thing = self.tex[-1 - self.width, -1 - self.height] + with pytest.raises(IndexError): + _ = tex[self.width, self.height] + with pytest.raises(IndexError): + _ = tex[-1 - self.width, -1 - self.height] def test_buffer(self): """Test the Buffer protocol implementation for RawTexture""" - mv = memoryview(self.tex) - - self.assertFalse(mv.readonly, 'buffer is readonly') - self.assertTrue(mv.c_contiguous, 'buffer is not contiguous') - self.assertEqual(mv.nbytes, self.size, 'buffer is the wrong size') - self.assertEqual(mv.format, 'B', 'buffer has the wrong format') - + tex = RawTexture(self.width, self.height) + mv = memoryview(tex) mv[:] = self.boilerplate_bytes - self.assertEqual(mv.tobytes(), self.boilerplate_bytes, 'incorrect buffer data') + + assert not mv.readonly + assert mv.c_contiguous + assert mv.nbytes == self.nbytes + assert mv.format == 'B' + assert mv.tobytes() == self.boilerplate_bytes + assert mv.tobytes() == tex.tobytes() def test_frombytes(self): """Test the frombytes factory function""" bytetex = RawTexture.frombytes(self.boilerplate_bytes, *self.boilerplate.size) - self.assertEqual(self.boilerplate_bytes, bytetex.tobytes(), 'Incorrect bytes after writing to buffer') + assert self.boilerplate_bytes == bytetex.tobytes()