Coverage for test_generate_gs1_datamatrix.py: 75%
54 statements
« prev ^ index » next coverage.py v6.4.1, created at 2022-07-12 15:55 +1000
« prev ^ index » next coverage.py v6.4.1, created at 2022-07-12 15:55 +1000
1from pathlib import Path
2import time
3from typing import Callable
4import pytest
5import io
8from gs1_barcode_enginer_wrapper import generate_gs1_datamatrix, Gs1GeneratorError
10# Barcode generation.
11# Accepts input text which will be ASCII encoded then
12# expressed as a barcode.
13# Output is PNG encoded data as `bytes`
14BarcodeGenerator = Callable[[str], bytes]
17def save_to_file(filename, data: bytes):
18 with open(filename, "wb") as f:
19 f.write(data)
22# takes about 0.38ms on mac, 0.76ms on pi
23def gs1_bartcode_engine_wrapper_generator(barcode_text: str) -> bytes:
24 # use wrapper around https://github.com/gs1/gs1-barcode-engine
25 # cloned to gs1-barcode-engine
27 module_x_dim_mm = 0.7
29 module_x_dim_inches = module_x_dim_mm * 0.0393701
30 dpi = 157.35
32 bmp_data = generate_gs1_datamatrix(
33 barcode_text,
34 dm_rows=22,
35 dm_cols=22,
36 x_undercut=0,
37 y_undercut=0,
38 scaling={"resolution": dpi, "target_x_dim": module_x_dim_inches},
39 )
41 save_to_file("output/gs1_barcode_enginer_wrapper.bmp", bmp_data)
43 return bmp_data
46@pytest.fixture
47def good_barcode_text() -> str:
48 return "(01)94210325403182(30)2(3922)0460(93)TQ"
51@pytest.fixture(
52 params=[
53 pytest.param(
54 {
55 "test_string": "(01)94210325403182(30)2(3922asdasd)0460(93)TQ",
56 "expect_string_in_exception": "Unrecognised AI",
57 },
58 id="Nonsense in middle of valid barcode text",
59 ),
60 pytest.param(
61 {"test_string": "", "expect_string_in_exception": "Missing FNC1"},
62 id="Empty string",
63 ),
64 pytest.param(
65 {
66 "test_string": "This is nonsense",
67 "expect_string_in_exception": "Failed to parse AI data",
68 },
69 id="This is complete nonsense",
70 ),
71 ],
72)
73def bad_barcode_text(request) -> dict:
74 return request.param
77module_x_dim_mm = 0.7
78module_x_dim_inches = module_x_dim_mm * 0.0393701
79dpi = 157.35
82@pytest.fixture(
83 params=[
84 pytest.param(
85 {
86 "test_params": {
87 "dm_rows": 2000,
88 "dm_cols": 22,
89 "x_undercut": 0,
90 "y_undercut": 0,
91 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
92 },
93 "expect_string_in_exception": "Valid number of Data Matrix rows range is",
94 },
95 id="Huge number of rows",
96 ),
97 pytest.param(
98 {
99 "test_params": {
100 "dm_rows": 22,
101 "dm_cols": 24000,
102 "x_undercut": 0,
103 "y_undercut": 0,
104 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
105 },
106 "expect_string_in_exception": "Valid number of Data Matrix columns range is",
107 },
108 id="Huge number of columns",
109 ),
110 pytest.param(
111 {
112 "test_params": {
113 "dm_rows": 22,
114 "dm_cols": 22,
115 "x_undercut": 900,
116 "y_undercut": 0,
117 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
118 },
119 "expect_string_in_exception": "Valid X undercut range is",
120 },
121 id="Huge X undercut",
122 ),
123 pytest.param(
124 {
125 "test_params": {
126 "dm_rows": 22,
127 "dm_cols": 22,
128 "x_undercut": 0,
129 "y_undercut": 900,
130 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
131 },
132 "expect_string_in_exception": "Valid Y undercut range is",
133 },
134 id="Huge Y undercut",
135 ),
136 pytest.param(
137 {
138 "test_params": {
139 "dm_rows": 22,
140 "dm_cols": 22,
141 "x_undercut": 0,
142 "y_undercut": 0,
143 "scaling": {
144 "resolution": dpi,
145 "target_x_dim": module_x_dim_inches,
146 "min_x_dim": module_x_dim_inches,
147 "max_x_dim": module_x_dim_inches,
148 },
149 },
150 "expect_string_in_exception": "Impossible to plot X-dimension of",
151 },
152 id="Unreasonable/impossible dot scaling constraints",
153 ),
154 pytest.param(
155 {
156 "test_params": {
157 "dm_rows": 22,
158 "dm_cols": 22,
159 "x_undercut": 0,
160 "y_undercut": 0,
161 "scaling": {
162 "pix_mult": 5000000,
163 },
164 },
165 "expect_string_in_exception": "Valid X-dimension range is 1 to 100",
166 },
167 id="Unreasonable/impossible pixel scaling constraints",
168 ),
169 pytest.param(
170 {
171 "test_params": {
172 "dm_rows": 22,
173 "dm_cols": 22,
174 "x_undercut": 0,
175 "y_undercut": 0,
176 "scaling": {
177 "resolution": 999999999,
178 "target_x_dim": module_x_dim_inches,
179 "min_x_dim": module_x_dim_inches,
180 "max_x_dim": module_x_dim_inches,
181 },
182 },
183 "expect_string_in_exception": "Valid X-dimension range is 1 to 100",
184 },
185 id="Dot scaling: resolution probably out of range",
186 ),
187 ],
188)
189def bad_generation_params(request) -> dict:
190 return request.param
193@pytest.fixture
194def output_dir() -> Path:
195 DIR = "output"
196 path = Path(DIR)
197 for f in path.glob("*.*"): 197 ↛ 200line 197 didn't jump to line 200, because the loop on line 197 didn't complete
198 f.unlink()
200 assert path.is_dir
201 assert len(list(path.glob("*.*"))) == 0
203 yield path
205 assert len(list(path.glob("*.*"))) == 1
208@pytest.fixture(
209 params=[
210 pytest.param(
211 {
212 "dm_rows": 22,
213 "dm_cols": 22,
214 "x_undercut": 0,
215 "y_undercut": 0,
216 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
217 },
218 id="Standard",
219 ),
220 pytest.param(
221 {},
222 id="No params",
223 ),
224 pytest.param(
225 {
226 "dm_rows": 22,
227 },
228 id="dm_rows only",
229 ),
230 pytest.param(
231 {
232 "dm_cols": 22,
233 },
234 id="dm_cols only",
235 ),
236 pytest.param(
237 {
238 "x_undercut": 1,
239 "scaling": {"pix_mult": 50},
240 },
241 id="x undercut only (default scaling overwritten to make this possible)",
242 ),
243 pytest.param(
244 {
245 "y_undercut": 1,
246 "scaling": {"pix_mult": 50},
247 },
248 id="y undercut only (default scaling overwritten to make this possible)",
249 ),
250 pytest.param(
251 {
252 "x_undercut": 1,
253 "y_undercut": 1,
254 "scaling": {"pix_mult": 50},
255 },
256 id="Both x and y undercut (default scaling overwritten to make this possible)",
257 ),
258 pytest.param(
259 {
260 "scaling": {"resolution": dpi, "target_x_dim": module_x_dim_inches},
261 },
262 id="Device dot (i.e. physical dimensions e.g. inches) scaling, only target_x_dim defined",
263 ),
264 pytest.param(
265 {
266 "scaling": {
267 "resolution": 300,
268 "min_x_dim": 0.02,
269 "target_x_dim": 0.03,
270 "max_x_dim": 0.04,
271 },
272 },
273 id="Device dot (i.e. physical dimensions e.g. inches) scaling, only target_x_dim defined",
274 ),
275 pytest.param(
276 {
277 "scaling": {"pix_mult": 50},
278 },
279 id="Pixel-based (i.e. pixels only, not physical dimensions) scaling scaling only",
280 ),
281 ],
282)
283def good_generation_params(request) -> dict:
284 return request.param
287def test_good_params(good_barcode_text, good_generation_params: dict, output_dir: Path):
288 bmp_data = generate_gs1_datamatrix(good_barcode_text, **good_generation_params)
289 save_to_file(output_dir / "gs1_barcode_enginer_wrapper.bmp", bmp_data)
292def test_bad_input(bad_barcode_text: dict):
293 with pytest.raises(Gs1GeneratorError) as exc:
294 barcode_bytes = gs1_bartcode_engine_wrapper_generator(
295 bad_barcode_text["test_string"]
296 )
298 assert bad_barcode_text["expect_string_in_exception"] in str(exc)
301def test_bad_generation_params(good_barcode_text, bad_generation_params: dict):
302 test_params = bad_generation_params["test_params"]
303 with pytest.raises(Gs1GeneratorError) as exc:
304 bmp_data = generate_gs1_datamatrix(good_barcode_text, **test_params)
306 assert bad_generation_params["expect_string_in_exception"] in str(exc)