Add a basic test harness
- ID
ce05b0d- date
2024-06-06 06:39:51+00:00- author
Alex Chan <alex@alexwlchan.net>- parent
c2cdfab- message
Add a basic test harness- changed files
6 files, 129 additions, 14 deletions
Changed files
get_live_text.swift (2766) → get_live_text.swift (2834)
diff --git a/get_live_text.swift b/get_live_text.swift
index d796656..18a91c2 100755
--- a/get_live_text.swift
+++ b/get_live_text.swift
@@ -34,6 +34,8 @@
import Vision
+let SCRIPT_VERSION = "1.0.0"
+
// Process the results of the text-recognition request.
//
// This is based on the code in Apple's documentation, and prints the
@@ -52,21 +54,16 @@ func recognizeTextHandler(request: VNRequest, error: Error?) {
return observation.topCandidates(1).first?.string
}
- // Serialise to JSON
- do {
- let jsonData = try JSONSerialization.data(withJSONObject: recognizedStrings)
-
- if let JSONString = String(data: jsonData, encoding: String.Encoding.utf8) {
- print(JSONString)
- }
- } catch {
- fputs("Unable to serialise the result as JSON: \(error).\n", stderr)
- exit(1)
- }
+ print(recognizedStrings.joined(separator: " "))
}
// Given the path to an image, print a JSON array of text it contains.
func printTextInImage(imagePath: String) {
+ if !FileManager.default.fileExists(atPath: imagePath) {
+ fputs("Cannot find file at path: \(imagePath)\n", stderr)
+ exit(1)
+ }
+
let requestHandler = VNImageRequestHandler(
url: URL(fileURLWithPath: imagePath),
options: [:]
@@ -85,8 +82,14 @@ func printTextInImage(imagePath: String) {
let arguments = CommandLine.arguments
+if arguments.count == 2 && arguments[1] == "--version" {
+ let filename = (arguments[0] as NSString).lastPathComponent
+ print("\(filename) \(SCRIPT_VERSION)")
+ exit(0)
+}
+
if arguments.count != 2 {
- fputs("Usage: \(arguments[0]) PATH\n", stderr)
+ fputs("Usage: \(arguments[0]) <PATH>\n", stderr)
exit(1)
}
tests/fixtures/checkerboard.png (0) → tests/fixtures/checkerboard.png (1040)
diff --git a/tests/fixtures/checkerboard.png b/tests/fixtures/checkerboard.png
new file mode 100644
index 0000000..76a7412
Binary files /dev/null and b/tests/fixtures/checkerboard.png differ
tests/fixtures/with_text.png (0) → tests/fixtures/with_text.png (3222)
diff --git a/tests/fixtures/with_text.png b/tests/fixtures/with_text.png
new file mode 100644
index 0000000..e6c6832
Binary files /dev/null and b/tests/fixtures/with_text.png differ
tests/test_get_live_text.py (0) → tests/test_get_live_text.py (1979)
diff --git a/tests/test_get_live_text.py b/tests/test_get_live_text.py
new file mode 100755
index 0000000..62719ed
--- /dev/null
+++ b/tests/test_get_live_text.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+
+import os
+import pathlib
+import plistlib
+import re
+
+import pytest
+
+from utils import get_live_text
+
+
+def test_gets_empty_result_if_no_text() -> None:
+ result = get_live_text(["tests/fixtures/checkerboard.png"])
+
+ assert result == {
+ "returncode": 0,
+ "stdout": "\n",
+ "stderr": None,
+ }
+
+
+def test_gets_text_from_image() -> None:
+ result = get_live_text(["tests/fixtures/with_text.png"])
+
+ assert result == {
+ "returncode": 0,
+ "stdout": "This is an image with more than one block of text\n",
+ "stderr": None,
+ }
+
+
+def test_gives_useful_error_if_no_such_file() -> None:
+ result = get_live_text(["tests/fixtures/doesnotexist.gif"])
+
+ assert result == {
+ "returncode": 1,
+ "stdout": None,
+ "stderr": "Cannot find file at path: tests/fixtures/doesnotexist.gif\n",
+ }
+
+
+def test_gives_useful_error_if_cannot_recognize_image(tmp_path: pathlib.Path) -> None:
+ with open(tmp_path / "broken.tif", "wb") as outfile:
+ outfile.write(b"helloworld")
+
+ result = get_live_text([str(tmp_path / "broken.tif")])
+
+ assert result["returncode"] == 1
+ assert result["stdout"] is None
+ assert result["stderr"].startswith("Unable to recognise text:")
+
+
+@pytest.mark.parametrize(
+ "argv",
+ [
+ pytest.param([], id="no_arguments"),
+ pytest.param(["example.png", "example.gif", "--debug"], id="too_many_arguments"),
+ ],
+)
+def test_it_fails_if_you_supply_the_wrong_arguments(argv: list[str]) -> None:
+ result = get_live_text(argv)
+
+ assert result == {
+ "returncode": 1,
+ "stdout": None,
+ "stderr": "Usage: get_live_text.swift <PATH>\n",
+ }
+
+
+
+def test_prints_the_version() -> None:
+ result = get_live_text(["--version"])
+
+ assert result["returncode"] == 0
+ assert result["stderr"] is None
+ assert re.match(
+ r"^get_live_text.swift [0-9]+\.[0-9]+\.[0-9]+\n$", result["stdout"]
+ ), result["stdout"]
tests/test_truth.py (34) → tests/test_truth.py (0)
diff --git a/tests/test_truth.py b/tests/test_truth.py
deleted file mode 100644
index 29c6b40..0000000
--- a/tests/test_truth.py
+++ /dev/null
@@ -1,2 +0,0 @@
-def test_truth():
- assert True
tests/utils.py (0) → tests/utils.py (794)
diff --git a/tests/utils.py b/tests/utils.py
new file mode 100644
index 0000000..3b10776
--- /dev/null
+++ b/tests/utils.py
@@ -0,0 +1,35 @@
+import pathlib
+import subprocess
+import typing
+
+
+class CommandOutput(typing.TypedDict):
+ returncode: int
+ stdout: str | None
+ stderr: str | None
+
+
+def get_live_text(argv: list[str | pathlib.Path]) -> CommandOutput:
+ """
+ Run the ``get_live_text.swift`` script and return the result.
+ """
+ cmd = ["swift", "get_live_text.swift"] + [str(av) for av in argv]
+
+ proc = subprocess.Popen(
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ stdout, stderr = proc.communicate()
+
+ if stdout is not None:
+ stdout = stdout.decode("utf8")
+
+ if stderr is not None:
+ stderr = stderr.decode("utf8")
+
+ return CommandOutput(
+ returncode=proc.returncode,
+ stdout=stdout or None,
+ stderr=stderr or None,
+ )