test_mn1_rec.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. '''
  2. @author: olivier.massot, janv. 2019
  3. '''
  4. import logging
  5. import re
  6. from path import Path
  7. from MnCheck.core import mncheck
  8. from MnCheck.core.checking import SUCCESS, FAILURE, ERROR
  9. from MnCheck.test._base import SchemaTest
  10. from qgis.core import QgsCoordinateReferenceSystem, QgsGeometry, QgsPointXY #@UnresolvedImport
  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. raise AssertionError("Error was not logged: {}".format(err_msg))
  40. def test_load_layers(self):
  41. # cas initial: valide
  42. r = self.run_test("test_load_layers")
  43. self.assertEqual(r.title, 'Chargement des données')
  44. self.assertSuccess(r)
  45. self.assertEqual(len(r.errors), 0)
  46. # une couche manquante et une pk manquante
  47. _pk_ini = self.schema.Cable.pk
  48. try:
  49. self.schema.Artere.layer = None
  50. self.schema.Cable.pk = "not_a_qgis_field"
  51. r = self.run_test("test_load_layers", True)
  52. self.assertFailure(r)
  53. self.assertErrorLogged(r, ".*Couche manquante.*")
  54. self.assertErrorLogged(r, ".*Clef primaire manquante.*")
  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. crs = QgsCoordinateReferenceSystem()
  65. crs.createFromSrid(4473)
  66. self.schema.Artere.layer.setCrs(crs)
  67. r = self.run_test("test_scr", True)
  68. self.assertFailure(r)
  69. self.assertErrorLogged(r, f"Mauvaise projection.*")
  70. def test_structure_arteres(self):
  71. # cas initial: valide
  72. r = self.run_test("test_structure_arteres")
  73. self.assertEqual(r.title, 'Structure des données: Artères')
  74. self.assertSuccess(r)
  75. self.assertEqual(len(r.errors), 0)
  76. # valeur non autorisée
  77. self.checker.arteres[0].AR_ID_INSE = "invalid"
  78. r = self.run_test("test_structure_arteres", True)
  79. self.assertFailure(r)
  80. def test_structure_cables(self):
  81. # cas initial: valide
  82. r = self.run_test("test_structure_cables")
  83. self.assertEqual(r.title, 'Structure des données: Cables')
  84. self.assertSuccess(r)
  85. self.assertEqual(len(r.errors), 0)
  86. # valeur non autorisée
  87. self.checker.cables[0].CA_TYPE = "invalid"
  88. r = self.run_test("test_structure_cables", True)
  89. self.assertFailure(r)
  90. def test_structure_equipements(self):
  91. # cas initial: valide
  92. r = self.run_test("test_structure_equipements")
  93. self.assertEqual(r.title, 'Structure des données: Equipements')
  94. self.assertSuccess(r)
  95. self.assertEqual(len(r.errors), 0)
  96. # valeur non autorisée
  97. self.checker.equipements[0].EQ_TYPE = "invalid"
  98. r = self.run_test("test_structure_equipements", True)
  99. self.assertFailure(r)
  100. def test_structure_noeuds(self):
  101. # cas initial: valide
  102. r = self.run_test("test_structure_noeuds")
  103. self.assertEqual(r.title, 'Structure des données: Noeuds')
  104. self.assertSuccess(r)
  105. self.assertEqual(len(r.errors), 0)
  106. # valeur non autorisée
  107. self.checker.noeuds[0].NO_ID_INSE = "invalid"
  108. r = self.run_test("test_structure_noeuds", True)
  109. self.assertFailure(r)
  110. def test_structure_tranchees(self):
  111. # cas initial: valide
  112. r = self.run_test("test_structure_tranchees")
  113. self.assertEqual(r.title, 'Structure des données: Tranchées')
  114. self.assertSuccess(r)
  115. self.assertEqual(len(r.errors), 0)
  116. # valeur non autorisée
  117. self.checker.tranchees[0].TR_REVET = "invalid"
  118. r = self.run_test("test_structure_tranchees", True)
  119. self.assertFailure(r)
  120. def test_structure_zapbos(self):
  121. # cas initial: valide
  122. r = self.run_test("test_structure_zapbos")
  123. self.assertEqual(r.title, 'Structure des données: Zapbos')
  124. self.assertSuccess(r)
  125. self.assertEqual(len(r.errors), 0)
  126. # valeur non autorisée
  127. self.checker.zapbos[0].STATUT = "invalid"
  128. r = self.run_test("test_structure_zapbos", True)
  129. self.assertFailure(r)
  130. def test_geometry_validity(self):
  131. # cas initial: valide
  132. r = self.run_test("test_geometry_validity")
  133. self.assertEqual(r.title, 'Contrôle de la validité des géométries')
  134. self.assertSuccess(r)
  135. self.assertEqual(len(r.errors), 0)
  136. # géométrie invalide
  137. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  138. r = self.run_test("test_geometry_validity", True)
  139. self.assertFailure(r)
  140. self.assertErrorLogged(r, "La géométrie de l'objet est invalide")
  141. def test_geometry_type(self):
  142. # cas initial: valide
  143. r = self.run_test("test_geometry_type")
  144. self.assertEqual(r.title, 'Contrôle des types de géométries')
  145. self.assertSuccess(r)
  146. self.assertEqual(len(r.errors), 0)
  147. # type de géométrie invalide
  148. self.checker.arteres[0]._feature.setGeometry(QgsGeometry())
  149. r = self.run_test("test_geometry_type", True)
  150. self.assertFailure(r)
  151. self.assertErrorLogged(r, "Type de géométrie invalide.*")
  152. def test_bounding_box(self):
  153. # cas initial: valide
  154. r = self.run_test("test_bounding_box")
  155. self.assertEqual(r.title, 'Contrôle des emprises')
  156. self.assertSuccess(r)
  157. self.assertEqual(len(r.errors), 0)
  158. # hors de l'emprise
  159. self.checker.noeuds[0]._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  160. r = self.run_test("test_bounding_box", True)
  161. self.assertFailure(r)
  162. self.assertErrorLogged(r, "Hors de l'emprise autorisée")
  163. def test_duplicates(self):
  164. # cas initial: valide
  165. r = self.run_test("test_duplicates")
  166. self.assertEqual(r.title, 'Recherche de doublons')
  167. self.assertSuccess(r)
  168. self.assertEqual(len(r.errors), 0)
  169. # cas de doublon
  170. self.checker.noeuds[0].NO_NOM = self.checker.noeuds[1].NO_NOM
  171. r = self.run_test("test_duplicates", True)
  172. self.assertFailure(r)
  173. self.assertErrorLogged(r, "Doublons dans le champs NO_NOM")
  174. def test_constraints_arteres_noeuds(self):
  175. # cas initial: valide
  176. r = self.run_test("test_constraints_arteres_noeuds")
  177. self.assertEqual(r.title, 'Application des contraintes: Artères / Noeuds')
  178. self.assertSuccess(r)
  179. self.assertEqual(len(r.errors), 0)
  180. # contrainte invalide
  181. self.checker.arteres[0].noeud_a = None
  182. r = self.run_test("test_constraints_arteres_noeuds", True)
  183. self.assertFailure(r)
  184. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  185. def test_constraints_cables_equipements(self):
  186. # cas initial: valide
  187. r = self.run_test("test_constraints_cables_equipements")
  188. self.assertEqual(r.title, 'Application des contraintes: Equipements / Cables')
  189. self.assertSuccess(r)
  190. self.assertEqual(len(r.errors), 0)
  191. # contrainte invalide
  192. self.checker.cables[0].equipement_a = None
  193. r = self.run_test("test_constraints_cables_equipements", True)
  194. self.assertFailure(r)
  195. self.assertErrorLogged(r, "L'équipement lié '.+' n'existe pas*")
  196. def test_constraints_cables_equipements_b(self):
  197. # cas initial: valide
  198. r = self.run_test("test_constraints_cables_equipements_b")
  199. self.assertEqual(r.title, 'Application des contraintes: Equipements B')
  200. self.assertSuccess(r)
  201. self.assertEqual(len(r.errors), 0)
  202. # contrainte invalide
  203. for cable in self.checker.cables:
  204. cable.CA_EQ_B = ""
  205. r = self.run_test("test_constraints_cables_equipements_b", True)
  206. self.assertFailure(r)
  207. self.assertErrorLogged(r, "L'equipement '.+' n'est l'équipement B d'aucun cable.+")
  208. def test_constraints_equipements_noeuds(self):
  209. # cas initial: valide
  210. r = self.run_test("test_constraints_equipements_noeuds")
  211. self.assertEqual(r.title, 'Application des contraintes: Noeuds / Equipements')
  212. self.assertSuccess(r)
  213. self.assertEqual(len(r.errors), 0)
  214. # contrainte invalide
  215. self.checker.equipements[0].noeud = None
  216. r = self.run_test("test_constraints_equipements_noeuds", True)
  217. self.assertFailure(r)
  218. self.assertErrorLogged(r, "Le noeud lié '.+' n'existe pas")
  219. def test_graphic_duplicates(self):
  220. # cas initial: valide
  221. r = self.run_test("test_graphic_duplicates")
  222. self.assertEqual(r.title, 'Recherche de doublons graphiques')
  223. self.assertSuccess(r)
  224. self.assertEqual(len(r.errors), 0)
  225. # doublon graphique
  226. self.checker.noeuds[0]._feature.setGeometry(self.checker.noeuds[1]._feature.geometry())
  227. r = self.run_test("test_graphic_duplicates", True)
  228. self.assertFailure(r)
  229. self.assertErrorLogged(r, "Une entité graphique est dupliquée")
  230. def test_positions_noeuds(self):
  231. # cas initial: valide
  232. r = self.run_test("test_positions_noeuds")
  233. self.assertEqual(r.title, 'Topologie: Noeuds / Artères')
  234. self.assertSuccess(r)
  235. self.assertEqual(len(r.errors), 0)
  236. # erreur topo
  237. self.checker.arteres[0].noeud_b._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  238. r = self.run_test("test_positions_noeuds", True)
  239. self.assertFailure(r)
  240. self.assertErrorLogged(r, "Le noeud B n'est pas aux coordonnées attendues.*")
  241. def test_positions_equipements(self):
  242. # cas initial: valide
  243. r = self.run_test("test_positions_equipements")
  244. self.assertEqual(r.title, 'Topologie: Equipements / Cables')
  245. self.assertSuccess(r)
  246. self.assertEqual(len(r.errors), 0)
  247. # erreur topo
  248. self.checker.cables[0].equipement_b.noeud._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  249. r = self.run_test("test_positions_equipements", True)
  250. self.assertFailure(r)
  251. self.assertErrorLogged(r, "L'équipement B n'est pas aux coordonnées attendues.*")
  252. def test_tranchee_artere(self):
  253. # cas initial: valide
  254. r = self.run_test("test_tranchee_artere")
  255. self.assertEqual(r.title, 'Topologie: Tranchées / Artères')
  256. self.assertSuccess(r)
  257. self.assertEqual(len(r.errors), 0)
  258. # erreur topo
  259. new_geom = self.checker.tranchees[0]._feature.geometry()
  260. new_geom.translate(10000, 10000)
  261. self.checker.tranchees[0]._feature.setGeometry(new_geom)
  262. r = self.run_test("test_tranchee_artere", True)
  263. self.assertFailure(r)
  264. self.assertErrorLogged(r, "Tranchée ou portion de tranchée sans artère")
  265. def test_cable_artere(self):
  266. # cas initial: valide
  267. r = self.run_test("test_cable_artere")
  268. self.assertEqual(r.title, 'Topologie: Cables / Artères')
  269. self.assertSuccess(r)
  270. self.assertEqual(len(r.errors), 0)
  271. # erreur topo
  272. self.checker.cables[0].CA_COMMENT = ""
  273. new_geom = self.checker.cables[0]._feature.geometry()
  274. new_geom.translate(10000, 10000)
  275. self.checker.cables[0]._feature.setGeometry(new_geom)
  276. r = self.run_test("test_cable_artere", True)
  277. self.assertFailure(r)
  278. self.assertErrorLogged(r, "Cable ou portion de cable sans artère")
  279. def test_artere_cable(self):
  280. # cas initial: valide
  281. r = self.run_test("test_artere_cable")
  282. self.assertEqual(r.title, 'Topologie: Artères / Cables')
  283. self.assertSuccess(r)
  284. self.assertEqual(len(r.errors), 0)
  285. # erreur topo
  286. self.checker.arteres[0].AR_COMMENT = ""
  287. new_geom = self.checker.arteres[0]._feature.geometry()
  288. new_geom.translate(10000, 10000)
  289. self.checker.arteres[0]._feature.setGeometry(new_geom)
  290. r = self.run_test("test_artere_cable", True)
  291. self.assertFailure(r)
  292. self.assertErrorLogged(r, "Artère ou portion d'artère sans cable")
  293. def test_arteres_enterrees(self):
  294. # cas initial: valide
  295. r = self.run_test("test_arteres_enterrees")
  296. self.assertEqual(r.title, 'Données des artères enterrées')
  297. self.assertSuccess(r)
  298. self.assertEqual(len(r.errors), 0)
  299. self.checker.arteres[0].AR_TYPE_FO = "PVC"
  300. del self.checker.arteres[0].__dict__["AR_NB_FOUR"]
  301. self.checker.arteres[0].AR_FOU_DIS = ""
  302. r = self.run_test("test_arteres_enterrees", True)
  303. self.assertFailure(r)
  304. self.assertErrorLogged(r, "Le champs est obligatoire: AR_NB_FOUR")
  305. self.assertErrorLogged(r, "Le champs doit être renseigné: AR_FOU_DIS")
  306. def test_dates_install(self):
  307. """ Dates d'installation
  308. Vérifie que les dates d'installation sont renseignées pour les équipements en service """
  309. # cas initial: valide
  310. r = self.run_test("test_dates_install")
  311. self.assertEqual(r.title, "Dates d'installation")
  312. self.assertSuccess(r)
  313. self.assertEqual(len(r.errors), 0)
  314. self.checker.cables[0].CA_STATUT = "REC"
  315. self.checker.cables[0].CA_DATE_IN = ""
  316. r = self.run_test("test_dates_install", True)
  317. self.assertFailure(r)
  318. self.assertErrorLogged(r, "Date d'installation \(CA_DATE_IN\) manquante")
  319. def test_largeur_tranchees(self):
  320. # cas initial: valide
  321. r = self.run_test("test_largeur_tranchees")
  322. self.assertEqual(r.title, "Tranchées: Dimensions")
  323. self.assertSuccess(r)
  324. self.assertEqual(len(r.errors), 0)
  325. self.checker.tranchees[0].TR_MOD_POS = "TRANCHEE"
  326. self.checker.tranchees[0].TR_LARG = 0
  327. r = self.run_test("test_largeur_tranchees", True)
  328. self.assertFailure(r)
  329. self.assertErrorLogged(r, "La largeur de la tranchée doit être supérieure à 0")
  330. def test_prop_gest(self):
  331. # cas initial: valide
  332. r = self.run_test("test_prop_gest")
  333. self.assertEqual(r.title, "Propriétaires / Gestionnaires")
  334. self.assertSuccess(r)
  335. self.assertEqual(len(r.errors), 0)
  336. self.checker.arteres[0].AR_PRO_FOU = "ORANGE"
  337. self.checker.arteres[0].AR_GEST_FO = "ERDF"
  338. r = self.run_test("test_prop_gest", True)
  339. self.assertFailure(r)
  340. self.assertErrorLogged(r, "Propriétaire: ORANGE, gestionnaire\(s\) possible\(s\): ORANGE \(renseigné: ERDF\)")
  341. def test_comments(self):
  342. # cas initial: valide
  343. r = self.run_test("test_comments")
  344. self.assertEqual(r.title, "Présence de commentaires")
  345. self.assertSuccess(r)
  346. self.assertEqual(len(r.errors), 0)
  347. self.checker.equipements[0].EQ_STATUT = "APD"
  348. self.checker.equipements[0].EQ_COMMENT = ""
  349. r = self.run_test("test_comments", True)
  350. self.assertFailure(r)
  351. self.assertErrorLogged(r, "L'equipement n'est pas en REC, un commentaire devrait en préciser la raison")
  352. def test_dimensions_fourreaux(self):
  353. # cas initial: valide
  354. r = self.run_test("test_dimensions_fourreaux")
  355. self.assertEqual(r.title, 'Dimensions logiques: fourreaux')
  356. self.assertSuccess(r)
  357. self.assertEqual(len(r.errors), 0)
  358. # nombre de fourreaux incohérent
  359. self.checker.arteres[0].AR_FOU_DIS = 1000
  360. r = self.run_test("test_dimensions_fourreaux", True)
  361. self.assertFailure(r)
  362. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(AR_FOU_DIS\) doit être inférieur au nombre total \(AR_NB_FOUR\)")
  363. self.checker.arteres[0].AR_FOU_DIS = 0
  364. # nombre de fourreaux incohérent
  365. self.checker.cables[0].CA_NB_FO_U = 1000
  366. r = self.run_test("test_dimensions_fourreaux", True)
  367. self.assertFailure(r)
  368. self.assertErrorLogged(r, "Le nombre de fourreaux utilisés \(CA_NB_FO_U\) doit être inférieur au nombre total \(CA_NB_FO\)")
  369. self.checker.cables[0].CA_NB_FO_U = 0
  370. # nombre de fourreaux incohérent
  371. self.checker.cables[0].CA_NB_FO_D = 1000
  372. r = self.run_test("test_dimensions_fourreaux", True)
  373. self.assertFailure(r)
  374. self.assertErrorLogged(r, "Le nombre de fourreaux disponibles \(CA_NB_FO_D\) doit être inférieur au nombre total \(CA_NB_FO\)")
  375. def test_pbos(self):
  376. # cas initial: valide
  377. r = self.run_test("test_pbos")
  378. self.assertEqual(r.title, 'Topologie: PBO / ZAPBO')
  379. self.assertSuccess(r)
  380. self.assertEqual(len(r.errors), 0)
  381. # noms equipement / zapbo incoherents
  382. eq = next(e for e in self.checker.equipements if e.EQ_TYPE == "PBO")
  383. eq.EQ_NOM = "babidiboo"
  384. r = self.run_test("test_pbos", True)
  385. self.assertFailure(r)
  386. self.assertErrorLogged(r, "Le nom de la PBO ne coincide avec le nom d'aucune des ZAPBO qui le contiennent")
  387. # equipement hors zapbo
  388. _ini_geom = eq.noeud._feature.geometry()
  389. eq.noeud._feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0,0)))
  390. r = self.run_test("test_pbos", True)
  391. self.assertFailure(r)
  392. self.assertErrorLogged(r, "Le PBO n'est contenu dans aucune ZAPBO")
  393. def test_zapbos_prises(self):
  394. # cas initial: valide
  395. r = self.run_test("test_zapbos_prises")
  396. self.assertEqual(r.title, 'Topologie: Zapbos / Prises')
  397. self.assertSuccess(r)
  398. self.assertEqual(len(r.errors), 0)
  399. # pas de prise dans la zapbo
  400. new_geom = self.checker.zapbos[0]._feature.geometry()
  401. new_geom.translate(1000,1000)
  402. self.checker.zapbos[0]._feature.setGeometry(new_geom)
  403. r = self.run_test("test_zapbos_prises", True)
  404. self.assertFailure(r)
  405. self.assertErrorLogged(r, "La Zapbo ne contient aucune prise")
  406. # couche non chargée
  407. self.schema.Prise.layer = None
  408. r = self.run_test("test_zapbos_prises", True)
  409. self.assertError(r)
  410. self.assertErrorLogged(r, "La couche des prises n'est pas chargée")
  411. def test_pbo_dimension(self):
  412. # cas initial: valide
  413. r = self.run_test("test_pbo_dimension")
  414. self.assertEqual(r.title, 'Dimensionnement des PBO')
  415. self.assertSuccess(r)
  416. self.assertEqual(len(r.errors), 0)
  417. # couche non chargée
  418. self.schema.Prise.layer = None
  419. r = self.run_test("test_pbo_dimension", True)
  420. self.assertError(r)
  421. self.assertErrorLogged(r, "La couche des prises n'est pas chargée")