test_mn1_rec.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. '''
  2. @author: olivier.massot, janv. 2019
  3. '''
  4. from core import mncheck
  5. import logging
  6. from qgis.core import QgsCoordinateReferenceSystem, QgsGeometry, QgsPointXY
  7. import re
  8. from core.checking import SUCCESS, FAILURE
  9. from path import Path
  10. from test._base import SchemaTest
  11. logger = logging.getLogger("mncheck")
  12. class Test(SchemaTest):
  13. SCHEMA_NAME = "mn1_rec"
  14. PROJECT_FILE = Path(__file__).parent / 'projects' / 'mn1_rec' / '1_valid' / '1_valid.qgz'
  15. def setUp(self):
  16. SchemaTest.setUp(self)
  17. self.schema = mncheck.get_schema(self.SCHEMA_NAME)
  18. if not self.schema.checkers:
  19. raise AttributeError("Aucun testeur trouvé dans le schéma")
  20. self.checker = self.schema.checkers[0]()
  21. def run_test(self, test_name, dry=False):
  22. results = self.checker.run(test_name, dry)
  23. if len(results) == 0:
  24. raise Exception("No result for test")
  25. elif len(results) > 1:
  26. raise Exception("More than one result from test")
  27. return results[0]
  28. def assertSuccess(self, r):
  29. if not r.status == SUCCESS:
  30. raise AssertionError("Le test a échoué")
  31. def assertFailure(self, r):
  32. if not r.status == FAILURE:
  33. raise AssertionError("Le test n'aurait pas dû réussir")
  34. def assertErrorLogged(self, result, err_msg):
  35. if not any((re.fullmatch(err_msg, err.message) for err in result.errors)):
  36. print(result.errors)
  37. raise AssertionError("Error was not logged: {}".format(err_msg))
  38. def test_load_layers(self):
  39. # cas initial: valide
  40. r = self.run_test("test_load_layers")
  41. self.assertEqual(r.title, 'Chargement des données')
  42. self.assertSuccess(r)
  43. self.assertEqual(len(r.errors), 0)
  44. # une couche manquante et une pk manquante
  45. _pk_ini = self.schema.Cable.pk
  46. try:
  47. self.schema.Artere.layer = None
  48. self.schema.Cable.pk = "not_a_qgis_field"
  49. r = self.run_test("test_load_layers", True)
  50. self.assertFailure(r)
  51. self.assertErrorLogged(r, ".*Couche manquante.*")
  52. self.assertErrorLogged(r, ".*Clef primaire manquante.*")
  53. except:
  54. raise
  55. finally:
  56. self.schema.Cable.pk = _pk_ini
  57. def test_scr(self):
  58. # cas initial: valide
  59. r = self.run_test("test_scr")
  60. self.assertEqual(r.title, 'Contrôle des projections')
  61. self.assertSuccess(r)
  62. self.assertEqual(len(r.errors), 0)
  63. # mauvaise projection
  64. self.schema.Artere.layer.setCrs(QgsCoordinateReferenceSystem())
  65. r = self.run_test("test_scr", True)
  66. self.assertFailure(r)
  67. self.assertErrorLogged(r, f"Mauvaise projection.*")
  68. def test_structure_arteres(self):
  69. # cas initial: valide
  70. r = self.run_test("test_structure_arteres")
  71. self.assertEqual(r.title, 'Structure des données: Artères')
  72. self.assertSuccess(r)
  73. self.assertEqual(len(r.errors), 0)
  74. # valeur non autorisée
  75. self.checker.arteres[0].AR_ID_INSE = "invalid"
  76. r = self.run_test("test_structure_arteres", True)
  77. self.assertFailure(r)
  78. def test_structure_cables(self):
  79. # cas initial: valide
  80. r = self.run_test("test_structure_cables")
  81. self.assertEqual(r.title, 'Structure des données: Cables')
  82. self.assertSuccess(r)
  83. self.assertEqual(len(r.errors), 0)
  84. # valeur non autorisée
  85. self.checker.cables[0].CA_TYPE = "invalid"
  86. r = self.run_test("test_structure_cables", True)
  87. self.assertFailure(r)
  88. def test_structure_equipements(self):
  89. # cas initial: valide
  90. r = self.run_test("test_structure_equipements")
  91. self.assertEqual(r.title, 'Structure des données: Equipements')
  92. self.assertSuccess(r)
  93. self.assertEqual(len(r.errors), 0)
  94. # valeur non autorisée
  95. self.checker.equipements[0].EQ_TYPE = "invalid"
  96. r = self.run_test("test_structure_equipements", True)
  97. self.assertFailure(r)
  98. def test_structure_noeuds(self):
  99. # cas initial: valide
  100. r = self.run_test("test_structure_noeuds")
  101. self.assertEqual(r.title, 'Structure des données: Noeuds')
  102. self.assertSuccess(r)
  103. self.assertEqual(len(r.errors), 0)
  104. # valeur non autorisée
  105. self.checker.noeuds[0].NO_ID_INSE = "invalid"
  106. r = self.run_test("test_structure_noeuds", True)
  107. self.assertFailure(r)
  108. def test_structure_tranchees(self):
  109. # cas initial: valide
  110. r = self.run_test("test_structure_tranchees")
  111. self.assertEqual(r.title, 'Structure des données: Tranchées')
  112. self.assertSuccess(r)
  113. self.assertEqual(len(r.errors), 0)
  114. # valeur non autorisée
  115. self.checker.tranchees[0].TR_REVET = "invalid"
  116. r = self.run_test("test_structure_tranchees", True)
  117. self.assertFailure(r)
  118. def test_structure_zapbos(self):
  119. # cas initial: valide
  120. r = self.run_test("test_structure_zapbos")
  121. self.assertEqual(r.title, 'Structure des données: Zapbos')
  122. self.assertSuccess(r)
  123. self.assertEqual(len(r.errors), 0)
  124. # valeur non autorisée
  125. self.checker.zapbos[0].STATUT = "invalid"
  126. r = self.run_test("test_structure_zapbos", True)
  127. self.assertFailure(r)
  128. def test_geometry_validity(self):
  129. # cas initial: valide
  130. r = self.run_test("test_geometry_validity")
  131. self.assertEqual(r.title, 'Contrôle de la validité des géométries')
  132. self.assertSuccess(r)
  133. self.assertEqual(len(r.errors), 0)
  134. # géométrie invalide
  135. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  136. r = self.run_test("test_geometry_validity", True)
  137. self.assertFailure(r)
  138. self.assertErrorLogged(r, "La géométrie de l'objet est invalide")
  139. def test_geometry_type(self):
  140. # cas initial: valide
  141. r = self.run_test("test_geometry_type")
  142. self.assertEqual(r.title, 'Contrôle des types de géométries')
  143. self.assertSuccess(r)
  144. self.assertEqual(len(r.errors), 0)
  145. # type de géométrie invalide
  146. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  147. r = self.run_test("test_geometry_type", True)
  148. self.assertFailure(r)
  149. self.assertErrorLogged(r, "Type de géométrie invalide.*")
  150. def test_bounding_box(self):
  151. # cas initial: valide
  152. r = self.run_test("test_bounding_box")
  153. self.assertEqual(r.title, 'Contrôle des emprises')
  154. self.assertSuccess(r)
  155. self.assertEqual(len(r.errors), 0)
  156. # hors de l'emprise
  157. self.checker.noeuds[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  158. r = self.run_test("test_bounding_box", True)
  159. self.assertFailure(r)
  160. self.assertErrorLogged(r, "Hors de l'emprise autorisée")
  161. def test_duplicates(self):
  162. # cas initial: valide
  163. r = self.run_test("test_duplicates")
  164. self.assertEqual(r.title, 'Recherche de doublons')
  165. self.assertSuccess(r)
  166. self.assertEqual(len(r.errors), 0)
  167. # cas de doublon
  168. self.checker.noeuds[0].NO_NOM = self.checker.noeuds[1].NO_NOM
  169. r = self.run_test("test_duplicates", True)
  170. self.assertFailure(r)
  171. self.assertErrorLogged(r, "Doublons dans le champs NO_NOM")
  172. def test_constraints_arteres_noeuds(self):
  173. # cas initial: valide
  174. r = self.run_test("test_constraints_arteres_noeuds")
  175. self.assertEqual(r.title, 'Application des contraintes: Artères / Noeuds')
  176. self.assertSuccess(r)
  177. self.assertEqual(len(r.errors), 0)
  178. # contrainte invalide
  179. self.checker.arteres[0].noeud_a = None
  180. r = self.run_test("test_constraints_arteres_noeuds", True)
  181. self.assertFailure(r)
  182. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  183. def test_constraints_cables_equipements(self):
  184. # cas initial: valide
  185. r = self.run_test("test_constraints_cables_equipements")
  186. self.assertEqual(r.title, 'Application des contraintes: Equipements / Cables')
  187. self.assertSuccess(r)
  188. self.assertEqual(len(r.errors), 0)
  189. # contrainte invalide
  190. self.checker.cables[0].equipement_a = None
  191. r = self.run_test("test_constraints_cables_equipements", True)
  192. self.assertFailure(r)
  193. self.assertErrorLogged(r, "L'équipement lié '.+' n'existe pas*")
  194. def test_constraints_cables_equipements_b(self):
  195. # cas initial: valide
  196. r = self.run_test("test_constraints_cables_equipements_b")
  197. self.assertEqual(r.title, 'Application des contraintes: Equipements B')
  198. self.assertSuccess(r)
  199. self.assertEqual(len(r.errors), 0)
  200. # contrainte invalide
  201. for cable in self.checker.cables:
  202. cable.CA_EQ_B = ""
  203. r = self.run_test("test_constraints_cables_equipements_b", True)
  204. self.assertFailure(r)
  205. self.assertErrorLogged(r, "L'equipement '.+' n'est l'équipement B d'aucun cable.+")
  206. def test_constraints_equipements_noeuds(self):
  207. # cas initial: valide
  208. r = self.run_test("test_constraints_equipements_noeuds")
  209. self.assertEqual(r.title, 'Application des contraintes: Noeuds / Equipements')
  210. self.assertSuccess(r)
  211. self.assertEqual(len(r.errors), 0)
  212. # contrainte invalide
  213. self.checker.equipements[0].noeud = None
  214. r = self.run_test("test_constraints_equipements_noeuds", True)
  215. self.assertFailure(r)
  216. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  217. def test_graphic_duplicates(self):
  218. # cas initial: valide
  219. r = self.run_test("test_graphic_duplicates")
  220. self.assertEqual(r.title, 'Recherche de doublons graphiques')
  221. self.assertSuccess(r)
  222. self.assertEqual(len(r.errors), 0)
  223. # doublon graphique
  224. self.checker.noeuds[0]._feature.setGeometry(self.checker.noeuds[1]._feature.geometry())
  225. r = self.run_test("test_graphic_duplicates", True)
  226. self.assertFailure(r)
  227. self.assertErrorLogged(r, "Une entité graphique est dupliquée")
  228. def test_positions_noeuds(self):
  229. # cas initial: valide
  230. r = self.run_test("test_positions_noeuds")
  231. self.assertEqual(r.title, 'Topologie: Noeuds / Artères')
  232. self.assertSuccess(r)
  233. self.assertEqual(len(r.errors), 0)
  234. # erreur topo
  235. self.checker.noeuds[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  236. r = self.run_test("test_positions_noeuds", True)
  237. self.assertFailure(r)
  238. self.assertErrorLogged(r, "Pas de noeud aux coordonnées attendues.*")
  239. def test_positions_equipements(self):
  240. # cas initial: valide
  241. r = self.run_test("test_positions_equipements")
  242. self.assertEqual(r.title, 'Topologie: Equipements / Cables')
  243. self.assertSuccess(r)
  244. self.assertEqual(len(r.errors), 0)
  245. # erreur topo
  246. self.checker.cables[0].equipement_b.noeud._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  247. r = self.run_test("test_positions_equipements", True)
  248. self.assertFailure(r)
  249. self.assertErrorLogged(r, "Pas d'équipement aux coordonnées attendues.*")
  250. def test_tranchee_artere(self):
  251. # cas initial: valide
  252. r = self.run_test("test_tranchee_artere")
  253. self.assertEqual(r.title, 'Topologie: Tranchées / Artères')
  254. self.assertSuccess(r)
  255. self.assertEqual(len(r.errors), 0)
  256. # erreur topo
  257. new_geom = self.checker.tranchees[0]._feature.geometry()
  258. new_geom.translate(10000, 10000)
  259. self.checker.tranchees[0]._feature.setGeometry(new_geom)
  260. r = self.run_test("test_tranchee_artere", True)
  261. self.assertFailure(r)
  262. self.assertErrorLogged(r, "Tranchée ou portion de tranchée sans artère")
  263. def test_cable_artere(self):
  264. # cas initial: valide
  265. r = self.run_test("test_cable_artere")
  266. self.assertEqual(r.title, 'Topologie: Cables / Artères')
  267. self.assertSuccess(r)
  268. self.assertEqual(len(r.errors), 0)
  269. # erreur topo
  270. self.checker.cables[0].CA_COMMENT = ""
  271. new_geom = self.checker.cables[0]._feature.geometry()
  272. new_geom.translate(10000, 10000)
  273. self.checker.cables[0]._feature.setGeometry(new_geom)
  274. r = self.run_test("test_cable_artere", True)
  275. self.assertFailure(r)
  276. self.assertErrorLogged(r, "Cable ou portion de cable sans artère")
  277. def test_artere_cable(self):
  278. # cas initial: valide
  279. r = self.run_test("test_artere_cable")
  280. self.assertEqual(r.title, 'Topologie: Artères / Cables')
  281. self.assertSuccess(r)
  282. self.assertEqual(len(r.errors), 0)
  283. # erreur topo
  284. self.checker.arteres[0].AR_COMMENT = ""
  285. new_geom = self.checker.arteres[0]._feature.geometry()
  286. new_geom.translate(10000, 10000)
  287. self.checker.arteres[0]._feature.setGeometry(new_geom)
  288. r = self.run_test("test_artere_cable", True)
  289. self.assertFailure(r)
  290. self.assertErrorLogged(r, "Artère ou portion d'artère sans cable")
  291. def test_dimensions_fourreaux(self):
  292. # cas initial: valide
  293. r = self.run_test("test_dimensions_fourreaux")
  294. self.assertEqual(r.title, 'Dimensions logiques: fourreaux')
  295. self.assertSuccess(r)
  296. self.assertEqual(len(r.errors), 0)
  297. # nombre de fourreaux incohérent
  298. self.checker.arteres[0].AR_FOU_DIS = 1000
  299. r = self.run_test("test_dimensions_fourreaux", True)
  300. self.assertFailure(r)
  301. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(AR_FOU_DIS\) doit être inférieur au nombre total \(AR_NB_FOUR\)")
  302. self.checker.arteres[0].AR_FOU_DIS = 0
  303. # nombre de fourreaux incohérent
  304. self.checker.cables[0].CA_NB_FO_U = 1000
  305. r = self.run_test("test_dimensions_fourreaux", True)
  306. self.assertFailure(r)
  307. self.assertErrorLogged(r, "Le nombre de fourreaux utilisés \(CA_NB_FO_U\) doit être inférieur au nombre total \(CA_NB_FO\)")
  308. self.checker.cables[0].CA_NB_FO_U = 0
  309. # nombre de fourreaux incohérent
  310. self.checker.cables[0].CA_NB_FO_D = 1000
  311. r = self.run_test("test_dimensions_fourreaux", True)
  312. self.assertFailure(r)
  313. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(CA_NB_FO_D\) doit être inférieur au nombre total \(CA_NB_FO\)")
  314. def test_pbos(self):
  315. # cas initial: valide
  316. r = self.run_test("test_pbos")
  317. self.assertEqual(r.title, 'Topologie: PBO / ZAPBO')
  318. self.assertSuccess(r)
  319. self.assertEqual(len(r.errors), 0)
  320. # equipement hors zapbo
  321. _ini_geom = self.checker.equipements[0]._feature.geometry()
  322. self.checker.equipements[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  323. r = self.run_test("test_pbos", True)
  324. self.assertFailure(r)
  325. self.assertErrorLogged(r, "Le PBO n'est contenu dans aucune ZAPBO")
  326. self.checker.equipements[0]._feature.setGeometry(_ini_geom)
  327. # noms equipement / zapbo incoherents
  328. self.checker.equipements[0].EQ_NOM = "%__#123456789#__%"
  329. r = self.run_test("test_pbos", True)
  330. self.assertFailure(r)
  331. self.assertErrorLogged(r, "Le nom du PBO ne coincide avec le nom d'aucune des ZAPBO qui le contiennent")
  332. def test_zapbos_prises(self):
  333. # cas initial: valide
  334. r = self.run_test("test_zapbos_prises")
  335. self.assertEqual(r.title, 'Topologie: Zapbos / Prises')
  336. self.assertSuccess(r)
  337. self.assertEqual(len(r.errors), 0)
  338. def test_pbo_dimension(self):
  339. # cas initial: valide
  340. r = self.run_test("test_pbo_dimension")
  341. self.assertEqual(r.title, 'Dimensionnement des PBO')
  342. self.assertSuccess(r)
  343. self.assertEqual(len(r.errors), 0)