test_assertions.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. """
  2. Tests assertion methods.
  3. """
  4. import os
  5. import grass.script.core as gcore
  6. from grass.pygrass.modules import Module
  7. from grass.gunittest.case import TestCase
  8. from grass.gunittest.main import test
  9. from grass.gunittest.gmodules import SimpleModule
  10. class TestTextAssertions(TestCase):
  11. # pylint: disable=R0904
  12. std_newline = "aaa\nbbb\n"
  13. platfrom_newline = "aaa{nl}bbb{nl}".format(nl=os.linesep)
  14. def test_assertLooksLike(self):
  15. self.assertLooksLike("Generated map is <elevation>", "Generated map is <...>")
  16. self.assertRaises(
  17. self.failureException,
  18. self.assertLooksLike,
  19. "Generated map is elevation.",
  20. "Generated map is <...>",
  21. )
  22. self.assertLooksLike(
  23. "Projection string: '+proj=longlat +datum=WGS84'", "Projection string: ..."
  24. )
  25. def test_assertLooksLike_multiline(self):
  26. self.assertLooksLike("a=123\nb=456\nc=789", "a=...\nb=...\nc=...")
  27. def test_assertLooksLike_multiline_platform_dependent(self):
  28. self.assertLooksLike(
  29. "a=123\nb=456\nc=789", "a=...{nl}b=...{nl}c=...".format(nl=os.linesep)
  30. )
  31. def test_assertLooksLike_numbers(self):
  32. self.assertLooksLike("abc = 125521", "abc = 125...")
  33. self.assertLooksLike("abc = 689.156", "abc = 689...")
  34. self.assertLooksLike("abc = 689.159589", "abc = 689.15...")
  35. # this should fail according to the implementation
  36. # first three dots are considered as ellipses
  37. self.assertRaises(
  38. self.failureException,
  39. self.assertLooksLike,
  40. "abc = 689.159589",
  41. "abc = 689....",
  42. )
  43. def do_all_combidnations(self, first, second, function):
  44. function(first, first)
  45. function(first, second)
  46. function(second, first)
  47. function(second, second)
  48. def test_assertMultiLineEqual(self):
  49. r"""Test different combinations of ``\n`` and os.linesep"""
  50. self.do_all_combidnations(
  51. self.std_newline, self.platfrom_newline, function=self.assertMultiLineEqual
  52. )
  53. def test_assertMultiLineEqual_raises(self):
  54. """Test mixed line endings"""
  55. self.assertRaises(
  56. self.failureException,
  57. self.assertMultiLineEqual,
  58. "aaa\n\rbbb\r",
  59. "aaa\nbbb\n",
  60. )
  61. def test_assertEqual(self):
  62. """Test for of newlines for strings (uses overwritten assertMultiLineEqual())"""
  63. self.do_all_combidnations(
  64. self.std_newline, self.platfrom_newline, function=self.assertEqual
  65. )
  66. def test_assertEqual_raises(self):
  67. """Test mixed line endings"""
  68. self.assertRaises(
  69. self.failureException, self.assertEqual, "aaa\n\rbbb\r", "aaa\nbbb\n"
  70. )
  71. R_UNIVAR_ELEVATION_SUBSET = """n=2025000
  72. null_cells=0
  73. min=55.5787925720215
  74. max=156.329864501953
  75. """
  76. RANDOM_KEYVALUES = """abc=2025000
  77. aaa=55.5787925720215
  78. bbb=156.329864501953
  79. """
  80. R_INFO_ELEVATION_SUBSET = """rows=1350
  81. cols=1500
  82. cells=2025000
  83. datatype=FCELL
  84. """
  85. # r.info -gre map=elevation
  86. ELEVATION_MAPSET_DICT = {"mapset": "PERMANENT"}
  87. # r.univar map=elevation
  88. ELEVATION_MINMAX = """min=55.5787925720215
  89. max=156.329864501953
  90. """
  91. # values rounded manually to maximal expected perecision
  92. ELEVATION_MINMAX_DICT = {"min": 55.58, "max": 156.33}
  93. class TestAssertModuleKeyValue(TestCase):
  94. """Test usage of `assertModuleKeyValue` method."""
  95. # pylint: disable=R0904
  96. @classmethod
  97. def setUpClass(cls):
  98. cls.use_temp_region()
  99. cls.runModule(SimpleModule("g.region", raster="elevation"))
  100. @classmethod
  101. def tearDownClass(cls):
  102. cls.del_temp_region()
  103. def test_pygrass_module(self):
  104. """Test syntax with Module and required parameters as module"""
  105. module = Module("r.info", map="elevation", flags="gr", run_=False, finish_=True)
  106. self.assertModuleKeyValue(
  107. module, reference=dict(min=55.58, max=156.33), precision=0.01, sep="="
  108. )
  109. def test_pygrass_simple_module(self):
  110. """Test syntax with SimpleModule as module"""
  111. module = SimpleModule("r.info", map="elevation", flags="gr")
  112. self.assertModuleKeyValue(
  113. module, reference=dict(min=55.58, max=156.33), precision=0.01, sep="="
  114. )
  115. def test_direct_parameters(self):
  116. """Test syntax with module and its parameters as function parameters"""
  117. self.assertModuleKeyValue(
  118. "r.info",
  119. map="elevation",
  120. flags="gr",
  121. reference=dict(min=55.58, max=156.33),
  122. precision=0.01,
  123. sep="=",
  124. )
  125. def test_parameters_parameter(self):
  126. """Test syntax with module parameters in one parameters dictionary"""
  127. self.assertModuleKeyValue(
  128. module="r.info",
  129. parameters=dict(map="elevation", flags="gr"),
  130. reference=dict(min=55.58, max=156.33),
  131. precision=0.01,
  132. sep="=",
  133. )
  134. class TestRasterMapAssertions(TestCase):
  135. # pylint: disable=R0904
  136. @classmethod
  137. def setUpClass(cls):
  138. cls.use_temp_region()
  139. # TODO: here we should actually not call self.runModule but call_module
  140. cls.runModule(SimpleModule("g.region", raster="elevation"))
  141. @classmethod
  142. def tearDownClass(cls):
  143. cls.del_temp_region()
  144. def test_assertRasterFitsUnivar(self):
  145. self.assertRasterFitsUnivar(
  146. "elevation", R_UNIVAR_ELEVATION_SUBSET, precision=0.01
  147. )
  148. self.assertRaises(
  149. self.failureException,
  150. self.assertRasterFitsUnivar,
  151. "geology",
  152. R_UNIVAR_ELEVATION_SUBSET,
  153. precision=0.01,
  154. )
  155. self.assertRaises(
  156. ValueError, self.assertRasterFitsUnivar, "elevation", RANDOM_KEYVALUES
  157. )
  158. def test_assertRasterFitsInfo(self):
  159. self.assertRasterFitsInfo("elevation", R_INFO_ELEVATION_SUBSET)
  160. self.assertRaises(
  161. self.failureException,
  162. self.assertRasterFitsInfo,
  163. "geology",
  164. R_INFO_ELEVATION_SUBSET,
  165. )
  166. self.assertRaises(
  167. ValueError, self.assertRasterFitsInfo, "elevation", RANDOM_KEYVALUES
  168. )
  169. def test_common_values_info_univar(self):
  170. self.assertRasterFitsUnivar("elevation", ELEVATION_MINMAX, precision=0.01)
  171. self.assertRasterFitsInfo("elevation", ELEVATION_MINMAX, precision=0.01)
  172. def test_dict_as_parameter(self):
  173. """This also tests if we are using r.info -e flag and that precision is
  174. not required for strings.
  175. """
  176. self.assertRasterFitsInfo("elevation", ELEVATION_MAPSET_DICT)
  177. def test_assertRastersNoDifference(self):
  178. """Test basic usage of assertRastersNoDifference"""
  179. self.assertRastersNoDifference(
  180. actual="elevation",
  181. reference="elevation",
  182. precision=0, # this might need to be increased
  183. msg="The same maps should have no difference",
  184. )
  185. self.assertRaises(
  186. self.failureException,
  187. self.assertRastersNoDifference,
  188. actual="elevation",
  189. reference="geology",
  190. precision=1,
  191. msg="Different maps should have difference",
  192. )
  193. def test_assertRastersNoDifference_mean(self):
  194. """Test usage of assertRastersNoDifference with mean"""
  195. self.assertRastersNoDifference(
  196. actual="elevation",
  197. reference="elevation",
  198. precision=0, # this might need to be increased
  199. statistics=dict(mean=0),
  200. msg="The difference of same maps should have small mean",
  201. )
  202. self.assertRaises(
  203. self.failureException,
  204. self.assertRastersNoDifference,
  205. actual="elevation",
  206. reference="geology",
  207. precision=1,
  208. statistics=dict(mean=0),
  209. msg="The difference of different maps should have huge mean",
  210. )
  211. def test_assertRastersEqual(self):
  212. """Test basic usage of assertRastersEqual"""
  213. self.assertRastersEqual(
  214. actual="lakes",
  215. reference="lakes",
  216. precision=0,
  217. msg="The same maps should have no difference",
  218. )
  219. self.assertRaises(
  220. self.failureException,
  221. self.assertRastersEqual,
  222. actual="elevation",
  223. reference="lakes",
  224. precision=1,
  225. msg="Different maps should have difference",
  226. )
  227. class TestMapExistsAssertions(TestCase):
  228. # pylint: disable=R0904
  229. raster_cell = "TestMapExistsAssertions_raster_cell"
  230. raster_dcell = "TestMapExistsAssertions_raster_dcell"
  231. raster3d = "TestMapExistsAssertions_raster3D"
  232. vector = "TestMapExistsAssertions_vector"
  233. @classmethod
  234. def setUpClass(cls):
  235. cls.use_temp_region()
  236. cls.runModule("g.region", n=10, e=10, s=0, w=0, t=10, b=0, res=1)
  237. cls.runModule("r.mapcalc", expression=cls.raster_cell + " = 1")
  238. cls.runModule("r.mapcalc", expression=cls.raster_dcell + " = 1.0")
  239. cls.runModule("r3.mapcalc", expression=cls.raster3d + " = 1.0")
  240. cls.runModule("v.edit", map=cls.vector, tool="create")
  241. @classmethod
  242. def tearDownClass(cls):
  243. cls.runModule(
  244. "g.remove",
  245. flags="f",
  246. type=["raster", "raster3d", "vector"],
  247. name=[cls.raster_cell, cls.raster_dcell, cls.raster3d, cls.vector],
  248. )
  249. cls.del_temp_region()
  250. def test_rast_cell_exists(self):
  251. self.assertRasterExists(self.raster_cell)
  252. def test_rast_dcell_exists(self):
  253. self.assertRasterExists(self.raster_dcell)
  254. def test_rast_does_not_exist(self):
  255. self.assertRaises(
  256. self.failureException, self.assertRasterExists, "does_not_exists"
  257. )
  258. def test_rast3d_exists(self):
  259. self.assertRaster3dExists(self.raster3d)
  260. def test_rast3d_does_not_exist(self):
  261. self.assertRaises(
  262. self.failureException, self.assertRaster3dExists, "does_not_exists"
  263. )
  264. def test_vect_exists(self):
  265. self.assertVectorExists(self.vector)
  266. def test_vect_does_not_exist(self):
  267. self.assertRaises(
  268. self.failureException, self.assertVectorExists, "does_not_exists"
  269. )
  270. def test_rast_does_not_exist_in_current_mapset(self):
  271. # expecting that there is elevation in PERMANENT
  272. # TODO: use skip decorator
  273. # TODO: add the same tests but for vect and rast3d
  274. self.assertRaises(
  275. self.failureException,
  276. self.assertRasterExists,
  277. "elevation",
  278. msg="Rasters from different mapsets should be ignored",
  279. )
  280. class TestFileAssertions(TestCase):
  281. # pylint: disable=R0904
  282. @classmethod
  283. def setUpClass(cls):
  284. # we expect WIND to be always present
  285. gisenv = gcore.gisenv()
  286. cls.existing_file = os.path.join(
  287. gisenv["GISDBASE"], gisenv["LOCATION_NAME"], "PERMANENT", "WIND"
  288. )
  289. cls.emtpy_file = cls.__name__ + "_this_is_an_empty_file"
  290. open(cls.emtpy_file, "w").close()
  291. cls.file_with_md5 = cls.__name__ + "_this_is_a_file_with_known_md5"
  292. file_content = "Content of the file with known MD5.\n"
  293. with open(cls.file_with_md5, "w") as f:
  294. f.write(file_content)
  295. # MD5 sum created using:
  296. # echo 'Content of the file with known MD5.' > some_file.txt
  297. # md5sum some_file.txt
  298. cls.file_md5 = "807bba4ffac4bb351bc3f27853009949"
  299. cls.file_with_same_content = cls.__name__ + "_file_with_same_content"
  300. with open(cls.file_with_same_content, "w") as f:
  301. f.write(file_content)
  302. cls.file_with_different_content = cls.__name__ + "_file_with_different_content"
  303. with open(cls.file_with_different_content, "w") as f:
  304. f.write(file_content + " Something else here.")
  305. @classmethod
  306. def tearDownClass(cls):
  307. os.remove(cls.emtpy_file)
  308. os.remove(cls.file_with_md5)
  309. os.remove(cls.file_with_same_content)
  310. os.remove(cls.file_with_different_content)
  311. def test_assertFileExists(self):
  312. self.assertFileExists(filename=self.existing_file)
  313. self.assertRaises(
  314. self.failureException,
  315. self.assertFileExists,
  316. filename="this_one_does_not_exists",
  317. )
  318. def test_assertFileExists_empty_file(self):
  319. self.assertFileExists(filename=self.emtpy_file, skip_size_check=True)
  320. self.assertRaises(
  321. self.failureException, self.assertFileExists, filename=self.emtpy_file
  322. )
  323. def test_assertFileMd5(self):
  324. self.assertFileMd5(filename=self.file_with_md5, md5=self.file_md5)
  325. self.assertRaises(
  326. self.failureException,
  327. self.assertFileMd5,
  328. filename=self.file_with_md5,
  329. md5="wrongmd5",
  330. )
  331. def test_assertFilesEqualMd5(self):
  332. self.assertFilesEqualMd5(
  333. filename=self.file_with_md5, reference=self.file_with_same_content
  334. )
  335. self.assertRaises(
  336. self.failureException,
  337. self.assertFilesEqualMd5,
  338. filename=self.file_with_md5,
  339. reference=self.file_with_different_content,
  340. )
  341. if __name__ == "__main__":
  342. test()