test_mn1_rec.py 18 KB

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