Coverage for test_generate_gs1_datamatrix.py: 75%

1 from pathlib import Path

2 import time

3 from typing import Callable

4 import pytest

5 import io

6

7

8 from gs1_barcode_enginer_wrapper import generate_gs1_datamatrix, Gs1GeneratorError

9

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`

14 BarcodeGenerator = Callable[[str], bytes]

15

16

17 def save_to_file(filename, data: bytes):

18 with open(filename, "wb") as f:

19 f.write(data)

20

21

22# takes about 0.38ms on mac, 0.76ms on pi

23 def 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

26

27 module_x_dim_mm = 0.7

28

29 module_x_dim_inches = module_x_dim_mm * 0.0393701

30 dpi = 157.35

31

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 )

40

41 save_to_file("output/gs1_barcode_enginer_wrapper.bmp", bmp_data)

42

43 return bmp_data

44

45

46@pytest.fixture

47 def good_barcode_text() -> str:

48 return "(01)94210325403182(30)2(3922)0460(93)TQ"

49

50

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)

73 def bad_barcode_text(request) -> dict:

74 return request.param

75

76

77 module_x_dim_mm = 0.7

78 module_x_dim_inches = module_x_dim_mm * 0.0393701

79 dpi = 157.35

80

81

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)

189 def bad_generation_params(request) -> dict:

190 return request.param

191

192

193@pytest.fixture

194 def 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()

199

200 assert path.is_dir

201 assert len(list(path.glob("*.*"))) == 0

202

203 yield path

204

205 assert len(list(path.glob("*.*"))) == 1

206

207

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)

283 def good_generation_params(request) -> dict:

284 return request.param

285

286

287 def 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)

290

291

292 def 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 )

297

298 assert bad_barcode_text["expect_string_in_exception"] in str(exc)

299

300

301 def 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)

305

306 assert bad_generation_params["expect_string_in_exception"] in str(exc)