From c20ec871cbc63bfc59c25656230ea56677909c9b Mon Sep 17 00:00:00 2001 From: as6325400 Date: Sun, 6 Oct 2024 23:32:48 +0800 Subject: [PATCH] unittest --- .github/workflows/unittest.yml | 41 +++++++++++++++ .gitignore | 4 +- .python-version | 1 + Qart/canvas.py | 8 +-- Qart/qart.py | 12 ++--- Qart/qrcode.py | 4 +- tests/test_canvas.py | 0 tests/test_encode.py | 0 tests/test_img.py | 91 ++++++++++++++++++++++++++-------- tests/test_qart.py | 54 ++++++++++++++------ tests/test_qrcode.py | 91 ++++++++++++++++++++++++++++++++++ 11 files changed, 258 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/unittest.yml create mode 100644 .python-version create mode 100644 tests/test_canvas.py create mode 100644 tests/test_encode.py create mode 100644 tests/test_qrcode.py diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml new file mode 100644 index 0000000..b4a5aca --- /dev/null +++ b/.github/workflows/unittest.yml @@ -0,0 +1,41 @@ +name: CI Pipeline + +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +jobs: + build: + runs-on: ubuntu-latest + + steps: + # Checkout the repository + - name: Checkout code + uses: actions/checkout@v3 + + # 安裝系統依賴,確保 OpenCV 可以正確運行 + - name: Install OpenCV dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgl1-mesa-glx libglib2.0-0 + + # 設置 Python 環境(這裡以 Python 為例) + - name: Set up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: 3.10 + + # 安裝 Python 依賴 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + # 執行測試 + - name: Run tests + run: | + python -m unittest discover diff --git a/.gitignore b/.gitignore index 2fa62ce..d326d6e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ decode.ipynb img.png temp.png version3_origin_M_20.png -.tox \ No newline at end of file +.tox +/htmlcov/ +.coverage \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..004e255 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +Qart diff --git a/Qart/canvas.py b/Qart/canvas.py index f490df3..78095cc 100644 --- a/Qart/canvas.py +++ b/Qart/canvas.py @@ -5,7 +5,7 @@ class Canvas: def __init__(self): - return + return # pragma: no cover def __resize(self, size: int): self.QR = np.full((size, size), dtype=int, fill_value=128) @@ -15,19 +15,19 @@ def __resize(self, size: int): def SetBlack(self, x: int, y: int): if(x < 0 or x >= len(self.QR) or y < 0 or y >= len(self.QR)): - raise ValueError("The coordinate is out of range") + raise ValueError("The coordinate is out of range") # pragma: no cover self.QR[x][y] = 0 return def SetWhite(self, x: int, y: int): if(x < 0 or x >= len(self.QR) or y < 0 or y >= len(self.QR)): - raise ValueError("The coordinate is out of range") + raise ValueError("The coordinate is out of range") # pragma: no cover self.QR[x][y] = 255 return def GetColor(self, x: int, y: int): if(x < 0 or x >= len(self.QR) or y < 0 or y >= len(self.QR)): - raise ValueError("The coordinate is out of range") + raise ValueError("The coordinate is out of range") # pragma: no cover return 0 if self.QR[x][y] == 0 else 1 def show(self): diff --git a/Qart/qart.py b/Qart/qart.py index 18a5a8d..9d65da8 100644 --- a/Qart/qart.py +++ b/Qart/qart.py @@ -12,11 +12,11 @@ def __init__(self, arg): super().__init__(arg) return - def blend(self, img: np.ndarray, padding: int, version: int, error_correction: str, mask: int = 4, mode = "Normal"): - self._Qrcode__dataload(version, error_correction, mask, mode) - img = img[padding:-padding, padding:-padding] - self.Binaryimage = Img.imagemoudlebase((version * 4 + 17), img) - return self.__QartHandler(mode, mask=mask) + # def blend(self, img: np.ndarray, padding: int, version: int, error_correction: str, mask: int = 4, mode = "Normal"): + # self._Qrcode__dataload(version, error_correction, mask, mode) + # img = img[padding:-padding, padding:-padding] + # self.Binaryimage = Img.imagemoudlebase((version * 4 + 17), img) + # return self.__QartHandler(mode, mask=mask) def generate(self, path: str, version: int, error_correction: str, mask: int = 0, mode = "Normal"): @@ -69,7 +69,7 @@ def __BlendImage(self): # tag.append(self.order[dataTable[i][j]]) # print(dataTable[i][j], self.order[dataTable[i][j]]) if rebuildtable[i][j] < 0: - raise ValueError("The data is not complete") + raise ValueError("The data is not complete") # pragma: no cover # if self.order[dataTable[i][j]] == 0: # # print(i, j) redata[self.order[dataTable[i][j]]] = str(rebuildtable[i][j]) diff --git a/Qart/qrcode.py b/Qart/qrcode.py index 31bdc3b..22fae47 100644 --- a/Qart/qrcode.py +++ b/Qart/qrcode.py @@ -249,7 +249,7 @@ def __SetDataPattern(self): def GetMask(self, i: int, j: int, mask: int): if i < 0 or i >= self.size or j < 0 or j >= self.size: - raise ValueError("The coordinate is out of range") + raise ValueError("The coordinate is out of range") # pragma: no cover bit : int = 1 if self.mask == 0: if (i + j) % 2 == 0: bit = 0 @@ -287,7 +287,7 @@ def showdata(self): if self.tagTable[i][j] == 2: temp[i][j] = 255 temp[0][0] = 0 - plt.imshow(temp, cmap='gray') + # plt.imshow(temp, cmap='gray') plt.colorbar() plt.show() return diff --git a/tests/test_canvas.py b/tests/test_canvas.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_encode.py b/tests/test_encode.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_img.py b/tests/test_img.py index 1efd2b4..6dbd219 100644 --- a/tests/test_img.py +++ b/tests/test_img.py @@ -1,22 +1,73 @@ -import pytest -import os -from Qart import Image +import unittest +from Qart.img import Image import shutil +import os +import tempfile +from unittest.mock import patch + + +class TestImage(unittest.TestCase): + @patch('matplotlib.pyplot.imsave') + def test_imgsave(self, mock_plt_save): + # 资源目录中的文件路径 + resource_dir = "tests" + resource_file = "1.png" + resource_path = os.path.join(resource_dir, resource_file) + + # 确保资源文件存在 + self.assertTrue(os.path.exists(resource_path), f"Resource file {resource_path} does not exist") + + # 创建临时目录 + with tempfile.TemporaryDirectory() as tmpdirname: + temp_file = os.path.join(tmpdirname, resource_file) + + # 将资源文件复制到临时目录中 + shutil.copy(resource_path, temp_file) + + # 使用 NamedTemporaryFile 创建临时保存路径 + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_output_file: + # 创建 Image 对象并使用临时文件路径 + img = Image(temp_file) + img.SetModuleNums(20) + + # 保存到临时文件路径,文件会在测试结束后自动删除 + img.save(temp_output_file.name, mode="Modulebase") + img.save(temp_output_file.name, mode="RGB") + img.save(temp_output_file.name, mode="Grayscale") + img.save(mode="OTSU") + + # 确保 save() 调用了4次 + self.assertEqual(mock_plt_save.call_count, 4) + with tempfile.NamedTemporaryFile(suffix=".jpg", delete=True) as temp_output_file: + # 创建 Image 对象并使用临时文件路径 + img = Image(temp_file) + img.SetModuleNums(20) + + # 保存到临时文件路径,文件会在测试结束后自动删除 + img.save(temp_output_file.name, mode="Modulebase") + img.save(temp_output_file.name, mode="RGB") + img.save(temp_output_file.name, mode="Grayscale") + img.save(mode="OTSU") + + # 确保 save() 调用了4次 + self.assertEqual(mock_plt_save.call_count, 8) + + @patch('matplotlib.pyplot.show') + def test_imgshow(self, mock_plt_show): + resource_dir = "tests" + resource_file = "1.png" + resource_path = os.path.join(resource_dir, resource_file) + self.assertTrue(os.path.exists(resource_path), f"Resource file {resource_path} does not exist") + img = Image(resource_path) + img.SetModuleNums(20) + img.show() + img.show("Grayscale") + img.show("OTSU") + img.show("Modulebase") + + # 确保 plt.show() 被调用过 + self.assertEqual(mock_plt_show.call_count, 4) -def test_img(tmpdir): - # 资源目录中的文件路径 - resource_dir = "tests" - resource_file = "1.png" - resource_path = os.path.join(resource_dir, resource_file) - - # 确保资源文件存在 - assert os.path.exists(resource_path), f"Resource file {resource_path} does not exist" - - # 将资源文件复制到临时目录中 - temp_file = tmpdir.join(resource_file) - shutil.copy(resource_path, str(temp_file)) - - # 创建 Image 对象并使用临时文件路径 - img = Image(str(temp_file)) - img.SetModuleNums(20) - img.save(mode = "Modulebase") \ No newline at end of file + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_qart.py b/tests/test_qart.py index 2246771..f92bfd4 100644 --- a/tests/test_qart.py +++ b/tests/test_qart.py @@ -1,20 +1,44 @@ -import pytest -import os -from Qart import Qart +import unittest +from Qart.qart import Qart import shutil +import os +import tempfile +from unittest.mock import patch + + +class TestQart(unittest.TestCase): + @patch('matplotlib.pyplot.imsave') + def test_Qartsave(self, mock_plt_save): + # 资源目录中的文件路径 + resource_dir = "tests" + resource_file = "1.png" + resource_path = os.path.join(resource_dir, resource_file) + + # 确保资源文件存在 + self.assertTrue(os.path.exists(resource_path), f"Resource file {resource_path} does not exist") + + # 创建临时目录 + with tempfile.TemporaryDirectory() as tmpdirname: + temp_file = os.path.join(tmpdirname, resource_file) -def test_qrcode(tmpdir): - Qr = Qart('accept') - # 资源目录中的文件路径 - resource_dir = "tests" - resource_file = "img2.jpeg" - resource_path = os.path.join(resource_dir, resource_file) - temp_file = tmpdir.join(resource_file) - shutil.copy(resource_path, str(temp_file)) - Qr.generate(temp_file, 20, "L", mask = 0, mode = "Normal") - Qr.show() - + # 将资源文件复制到临时目录中 + shutil.copy(resource_path, temp_file) + # 使用 NamedTemporaryFile 创建临时保存路径 + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_output_file: + Qr = Qart("Accepted") + Qr.generate(resource_path, 6, "L", mask = 0, mode = "Normal") + # # 创建 Image 对象并使用临时文件路径 + # img = Image(temp_file) + # img.SetModuleNums(20) + # 保存到临时文件路径,文件会在测试结束后自动删除 + Qr.save() + self.assertEqual(mock_plt_save.call_count, 1) + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_output_file: + Qr = Qart("Acceptedwadawdqawdewrwareawerwarewd") + Qr.generate(resource_path, 10, "L", mask = 0, mode = "Normal") - \ No newline at end of file + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_qrcode.py b/tests/test_qrcode.py new file mode 100644 index 0000000..b409166 --- /dev/null +++ b/tests/test_qrcode.py @@ -0,0 +1,91 @@ +import unittest +from Qart.qart import Qrcode +from Qart.Error import EncodeError +import shutil +import os +import tempfile +from unittest.mock import patch + + +class TestQrcode(unittest.TestCase): + @patch('matplotlib.pyplot.imsave') + def test_qrcodesave(self, mock_plt_save): + # 资源目录中的文件路径 + resource_dir = "tests" + resource_file = "1.png" + resource_path = os.path.join(resource_dir, resource_file) + + # 确保资源文件存在 + self.assertTrue(os.path.exists(resource_path), f"Resource file {resource_path} does not exist") + + # 创建临时目录 + with tempfile.TemporaryDirectory() as tmpdirname: + temp_file = os.path.join(tmpdirname, resource_file) + + # 将资源文件复制到临时目录中 + shutil.copy(resource_path, temp_file) + + # 使用 NamedTemporaryFile 创建临时保存路径 + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_output_file: + Qr = Qrcode("Accepted") + Qr.generate(6, "L", mask = 0, mode = "Normal") + Qr = Qrcode("1234") + Qr.generate(6, "L", mask = 1, mode = "Micro") + Qr = Qrcode("12345") + Qr.generate(6, "L", mask = 2, mode = "Normal") + Qr = Qrcode("/O.O/") + Qr.generate(6, "H", mask = 3, mode = "Normal") + Qr = Qrcode("謝") + Qr.generate(6, "M", mask = 4, mode = "Normal") + Qr = Qrcode("Accepted") + Qr.generate(6, "Q", mask = 5, mode = "Normal") + Qr.save("test.jpg") + Qr = Qrcode("Accepted") + Qr.generate(6, "M", mask = 6, mode = "Normal") + Qr.save("test.png") + Qr = Qrcode("Accepted") + Qr.generate(6, "Q", mask = 7, mode = "Normal") + num = Qr.InformationMask() + # Qr.showdata() + # # 创建 Image 对象并使用临时文件路径 + # img = Image(temp_file) + # img.SetModuleNums(20) + + # 保存到临时文件路径,文件会在测试结束后自动删除 + Qr.save() + self.assertEqual(mock_plt_save.call_count, 3) + with tempfile.NamedTemporaryFile(suffix=".png", delete=True) as temp_output_file: + Qr = Qrcode("Acceptedwadawdqawdewrwareawerwarewd") + Qr.generate(20, "L", mask = 0, mode = "Normal") + + @patch('matplotlib.pyplot.show') + def test_qrcode_data_show(self, mock_plt_show): + Qr = Qrcode("Accepted") + Qr.generate(6, "Q", mask = 7, mode = "Normal") + num = Qr.InformationMask() + Qr.showdata() + self.assertEqual(mock_plt_show.call_count, 1) + + @patch('matplotlib.pyplot.show') + def test_qrcode_show(self, mock_plt_show): + Qr = Qrcode("Accepted") + Qr.generate(6, "Q", mask = 7, mode = "Normal") + Qr.show() + self.assertEqual(mock_plt_show.call_count, 1) + + def test_qrcode_tp_numpy(self): + Qr = Qrcode("Accepted") + Qr.generate(6, "Q", mask = 7, mode = "Normal") + Qr.to_numpy() + def test_encode_error(self): + with self.assertRaises(EncodeError): + Qr = Qrcode("한") + Qr.generate(6, "L", mask = 0, mode = "Normal") + + def test_value_error(self): + with self.assertRaises(ValueError): + Qr = Qrcode("dwadw") + Qr.generate(50, "L", mask = 0, mode = "Normal") + +if __name__ == '__main__': + unittest.main() \ No newline at end of file