""" Tests assertion methods. """ import os import grass.script.core as gcore from grass.pygrass.modules import Module from grass.gunittest.case import TestCase from grass.gunittest.main import test from grass.gunittest.gmodules import SimpleModule class TestTextAssertions(TestCase): # pylint: disable=R0904 std_newline = "aaa\nbbb\n" platfrom_newline = "aaa{nl}bbb{nl}".format(nl=os.linesep) def test_assertLooksLike(self): self.assertLooksLike("Generated map is ", "Generated map is <...>") self.assertRaises( self.failureException, self.assertLooksLike, "Generated map is elevation.", "Generated map is <...>", ) self.assertLooksLike( "Projection string: '+proj=longlat +datum=WGS84'", "Projection string: ..." ) def test_assertLooksLike_multiline(self): self.assertLooksLike("a=123\nb=456\nc=789", "a=...\nb=...\nc=...") def test_assertLooksLike_multiline_platform_dependent(self): self.assertLooksLike( "a=123\nb=456\nc=789", "a=...{nl}b=...{nl}c=...".format(nl=os.linesep) ) def test_assertLooksLike_numbers(self): self.assertLooksLike("abc = 125521", "abc = 125...") self.assertLooksLike("abc = 689.156", "abc = 689...") self.assertLooksLike("abc = 689.159589", "abc = 689.15...") # this should fail according to the implementation # first three dots are considered as ellipses self.assertRaises( self.failureException, self.assertLooksLike, "abc = 689.159589", "abc = 689....", ) def do_all_combidnations(self, first, second, function): function(first, first) function(first, second) function(second, first) function(second, second) def test_assertMultiLineEqual(self): r"""Test different combinations of ``\n`` and os.linesep""" self.do_all_combidnations( self.std_newline, self.platfrom_newline, function=self.assertMultiLineEqual ) def test_assertMultiLineEqual_raises(self): """Test mixed line endings""" self.assertRaises( self.failureException, self.assertMultiLineEqual, "aaa\n\rbbb\r", "aaa\nbbb\n", ) def test_assertEqual(self): """Test for of newlines for strings (uses overwritten assertMultiLineEqual())""" self.do_all_combidnations( self.std_newline, self.platfrom_newline, function=self.assertEqual ) def test_assertEqual_raises(self): """Test mixed line endings""" self.assertRaises( self.failureException, self.assertEqual, "aaa\n\rbbb\r", "aaa\nbbb\n" ) R_UNIVAR_ELEVATION_SUBSET = """n=2025000 null_cells=0 min=55.5787925720215 max=156.329864501953 """ RANDOM_KEYVALUES = """abc=2025000 aaa=55.5787925720215 bbb=156.329864501953 """ R_INFO_ELEVATION_SUBSET = """rows=1350 cols=1500 cells=2025000 datatype=FCELL """ # r.info -gre map=elevation ELEVATION_MAPSET_DICT = {"mapset": "PERMANENT"} # r.univar map=elevation ELEVATION_MINMAX = """min=55.5787925720215 max=156.329864501953 """ # values rounded manually to maximal expected perecision ELEVATION_MINMAX_DICT = {"min": 55.58, "max": 156.33} class TestAssertModuleKeyValue(TestCase): """Test usage of `assertModuleKeyValue` method.""" # pylint: disable=R0904 @classmethod def setUpClass(cls): cls.use_temp_region() cls.runModule(SimpleModule("g.region", raster="elevation")) @classmethod def tearDownClass(cls): cls.del_temp_region() def test_pygrass_module(self): """Test syntax with Module and required parameters as module""" module = Module("r.info", map="elevation", flags="gr", run_=False, finish_=True) self.assertModuleKeyValue( module, reference=dict(min=55.58, max=156.33), precision=0.01, sep="=" ) def test_pygrass_simple_module(self): """Test syntax with SimpleModule as module""" module = SimpleModule("r.info", map="elevation", flags="gr") self.assertModuleKeyValue( module, reference=dict(min=55.58, max=156.33), precision=0.01, sep="=" ) def test_direct_parameters(self): """Test syntax with module and its parameters as function parameters""" self.assertModuleKeyValue( "r.info", map="elevation", flags="gr", reference=dict(min=55.58, max=156.33), precision=0.01, sep="=", ) def test_parameters_parameter(self): """Test syntax with module parameters in one parameters dictionary""" self.assertModuleKeyValue( module="r.info", parameters=dict(map="elevation", flags="gr"), reference=dict(min=55.58, max=156.33), precision=0.01, sep="=", ) class TestRasterMapAssertions(TestCase): # pylint: disable=R0904 @classmethod def setUpClass(cls): cls.use_temp_region() # TODO: here we should actually not call self.runModule but call_module cls.runModule(SimpleModule("g.region", raster="elevation")) @classmethod def tearDownClass(cls): cls.del_temp_region() def test_assertRasterFitsUnivar(self): self.assertRasterFitsUnivar( "elevation", R_UNIVAR_ELEVATION_SUBSET, precision=0.01 ) self.assertRaises( self.failureException, self.assertRasterFitsUnivar, "geology", R_UNIVAR_ELEVATION_SUBSET, precision=0.01, ) self.assertRaises( ValueError, self.assertRasterFitsUnivar, "elevation", RANDOM_KEYVALUES ) def test_assertRasterFitsInfo(self): self.assertRasterFitsInfo("elevation", R_INFO_ELEVATION_SUBSET) self.assertRaises( self.failureException, self.assertRasterFitsInfo, "geology", R_INFO_ELEVATION_SUBSET, ) self.assertRaises( ValueError, self.assertRasterFitsInfo, "elevation", RANDOM_KEYVALUES ) def test_common_values_info_univar(self): self.assertRasterFitsUnivar("elevation", ELEVATION_MINMAX, precision=0.01) self.assertRasterFitsInfo("elevation", ELEVATION_MINMAX, precision=0.01) def test_dict_as_parameter(self): """This also tests if we are using r.info -e flag and that precision is not required for strings. """ self.assertRasterFitsInfo("elevation", ELEVATION_MAPSET_DICT) def test_assertRastersNoDifference(self): """Test basic usage of assertRastersNoDifference""" self.assertRastersNoDifference( actual="elevation", reference="elevation", precision=0, # this might need to be increased msg="The same maps should have no difference", ) self.assertRaises( self.failureException, self.assertRastersNoDifference, actual="elevation", reference="geology", precision=1, msg="Different maps should have difference", ) def test_assertRastersNoDifference_mean(self): """Test usage of assertRastersNoDifference with mean""" self.assertRastersNoDifference( actual="elevation", reference="elevation", precision=0, # this might need to be increased statistics=dict(mean=0), msg="The difference of same maps should have small mean", ) self.assertRaises( self.failureException, self.assertRastersNoDifference, actual="elevation", reference="geology", precision=1, statistics=dict(mean=0), msg="The difference of different maps should have huge mean", ) def test_assertRastersEqual(self): """Test basic usage of assertRastersEqual""" self.assertRastersEqual( actual="lakes", reference="lakes", precision=0, msg="The same maps should have no difference", ) self.assertRaises( self.failureException, self.assertRastersEqual, actual="elevation", reference="lakes", precision=1, msg="Different maps should have difference", ) class TestMapExistsAssertions(TestCase): # pylint: disable=R0904 raster_cell = "TestMapExistsAssertions_raster_cell" raster_dcell = "TestMapExistsAssertions_raster_dcell" raster3d = "TestMapExistsAssertions_raster3D" vector = "TestMapExistsAssertions_vector" @classmethod def setUpClass(cls): cls.use_temp_region() cls.runModule("g.region", n=10, e=10, s=0, w=0, t=10, b=0, res=1) cls.runModule("r.mapcalc", expression=cls.raster_cell + " = 1") cls.runModule("r.mapcalc", expression=cls.raster_dcell + " = 1.0") cls.runModule("r3.mapcalc", expression=cls.raster3d + " = 1.0") cls.runModule("v.edit", map=cls.vector, tool="create") @classmethod def tearDownClass(cls): cls.runModule( "g.remove", flags="f", type=["raster", "raster3d", "vector"], name=[cls.raster_cell, cls.raster_dcell, cls.raster3d, cls.vector], ) cls.del_temp_region() def test_rast_cell_exists(self): self.assertRasterExists(self.raster_cell) def test_rast_dcell_exists(self): self.assertRasterExists(self.raster_dcell) def test_rast_does_not_exist(self): self.assertRaises( self.failureException, self.assertRasterExists, "does_not_exists" ) def test_rast3d_exists(self): self.assertRaster3dExists(self.raster3d) def test_rast3d_does_not_exist(self): self.assertRaises( self.failureException, self.assertRaster3dExists, "does_not_exists" ) def test_vect_exists(self): self.assertVectorExists(self.vector) def test_vect_does_not_exist(self): self.assertRaises( self.failureException, self.assertVectorExists, "does_not_exists" ) def test_rast_does_not_exist_in_current_mapset(self): # expecting that there is elevation in PERMANENT # TODO: use skip decorator # TODO: add the same tests but for vect and rast3d self.assertRaises( self.failureException, self.assertRasterExists, "elevation", msg="Rasters from different mapsets should be ignored", ) class TestFileAssertions(TestCase): # pylint: disable=R0904 @classmethod def setUpClass(cls): # we expect WIND to be always present gisenv = gcore.gisenv() cls.existing_file = os.path.join( gisenv["GISDBASE"], gisenv["LOCATION_NAME"], "PERMANENT", "WIND" ) cls.emtpy_file = cls.__name__ + "_this_is_an_empty_file" open(cls.emtpy_file, "w").close() cls.file_with_md5 = cls.__name__ + "_this_is_a_file_with_known_md5" file_content = "Content of the file with known MD5.\n" with open(cls.file_with_md5, "w") as f: f.write(file_content) # MD5 sum created using: # echo 'Content of the file with known MD5.' > some_file.txt # md5sum some_file.txt cls.file_md5 = "807bba4ffac4bb351bc3f27853009949" cls.file_with_same_content = cls.__name__ + "_file_with_same_content" with open(cls.file_with_same_content, "w") as f: f.write(file_content) cls.file_with_different_content = cls.__name__ + "_file_with_different_content" with open(cls.file_with_different_content, "w") as f: f.write(file_content + " Something else here.") @classmethod def tearDownClass(cls): os.remove(cls.emtpy_file) os.remove(cls.file_with_md5) os.remove(cls.file_with_same_content) os.remove(cls.file_with_different_content) def test_assertFileExists(self): self.assertFileExists(filename=self.existing_file) self.assertRaises( self.failureException, self.assertFileExists, filename="this_one_does_not_exists", ) def test_assertFileExists_empty_file(self): self.assertFileExists(filename=self.emtpy_file, skip_size_check=True) self.assertRaises( self.failureException, self.assertFileExists, filename=self.emtpy_file ) def test_assertFileMd5(self): self.assertFileMd5(filename=self.file_with_md5, md5=self.file_md5) self.assertRaises( self.failureException, self.assertFileMd5, filename=self.file_with_md5, md5="wrongmd5", ) def test_assertFilesEqualMd5(self): self.assertFilesEqualMd5( filename=self.file_with_md5, reference=self.file_with_same_content ) self.assertRaises( self.failureException, self.assertFilesEqualMd5, filename=self.file_with_md5, reference=self.file_with_different_content, ) if __name__ == "__main__": test()