path_test.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # -*- coding: utf-8 -*-
  2. import os
  3. import json
  4. import pytest
  5. from pathfinding.finder.a_star import AStarFinder
  6. from pathfinding.finder.best_first import BestFirst
  7. from pathfinding.finder.dijkstra import DijkstraFinder
  8. from pathfinding.finder.bi_a_star import BiAStarFinder
  9. from pathfinding.finder.ida_star import IDAStarFinder
  10. from pathfinding.finder.breadth_first import BreadthFirstFinder
  11. from pathfinding.finder.finder import ExecutionRunsException
  12. from pathfinding.finder.finder import ExecutionTimeException
  13. from pathfinding.core.grid import Grid
  14. from pathfinding.core.diagonal_movement import DiagonalMovement
  15. BASE_PATH = os.path.abspath(os.path.dirname(__file__))
  16. # test scenarios from Pathfinding.JS
  17. scenarios = os.path.join(BASE_PATH, 'path_test_scenarios.json')
  18. data = json.load(open(scenarios, 'r'))
  19. finders = [AStarFinder, BestFirst, BiAStarFinder, DijkstraFinder,
  20. IDAStarFinder, BreadthFirstFinder]
  21. TIME_LIMIT = 10 # give it a 10 second limit.
  22. def grid_from_scenario(scenario):
  23. inverse = scenario['inverse'] if 'inverse' in scenario else True
  24. grid = Grid(matrix=scenario['matrix'], inverse=inverse)
  25. start = grid.node(scenario['startX'], scenario['startY'])
  26. end = grid.node(scenario['endX'], scenario['endY'])
  27. return grid, start, end
  28. def test_path():
  29. """
  30. test scenarios defined in json file
  31. """
  32. for scenario in data:
  33. grid, start, end = grid_from_scenario(scenario)
  34. for find in finders:
  35. grid.cleanup()
  36. finder = find(time_limit=TIME_LIMIT)
  37. weighted = False
  38. if 'weighted' in scenario:
  39. weighted = scenario['weighted']
  40. if weighted and not finder.weighted:
  41. continue
  42. path, runs = finder.find_path(start, end, grid)
  43. print(find.__name__)
  44. print(grid.grid_str(path=path, start=start, end=end,
  45. show_weight=weighted))
  46. print('path: {}'.format(path))
  47. assert len(path) == scenario['expectedLength']
  48. def test_path_diagonal():
  49. # test diagonal movement
  50. for scenario in data:
  51. grid, start, end = grid_from_scenario(scenario)
  52. for find in finders:
  53. grid.cleanup()
  54. finder = find(diagonal_movement=DiagonalMovement.always,
  55. time_limit=TIME_LIMIT)
  56. weighted = False
  57. if 'weighted' in scenario:
  58. weighted = scenario['weighted']
  59. print(dir(find))
  60. if weighted and not finder.weighted:
  61. continue
  62. path, runs = finder.find_path(start, end, grid)
  63. print(find.__name__, runs, len(path))
  64. print(grid.grid_str(path=path, start=start, end=end,
  65. show_weight=weighted))
  66. print('path: {}'.format(path))
  67. assert len(path) == scenario['expectedDiagonalLength']
  68. def test_max_runs():
  69. grid, start, end = grid_from_scenario(data[1])
  70. for find in finders:
  71. grid.cleanup()
  72. finder = find(diagonal_movement=DiagonalMovement.always,
  73. time_limit=TIME_LIMIT, max_runs=3)
  74. with pytest.raises(ExecutionRunsException):
  75. path, runs = finder.find_path(start, end, grid)
  76. print('{} finishes after {} runs without exception'.format(
  77. find.__name__, finder.runs))
  78. msg = '{} needed to much iterations'.format(
  79. finder.__class__.__name__)
  80. assert(finder.runs <= 3), msg
  81. def test_time():
  82. grid, start, end = grid_from_scenario(data[1])
  83. for find in finders:
  84. grid.cleanup()
  85. finder = find(diagonal_movement=DiagonalMovement.always,
  86. time_limit=-.1)
  87. with pytest.raises(ExecutionTimeException):
  88. path, runs = finder.find_path(start, end, grid)
  89. print('{} finishes after {} runs without exception'.format(
  90. find.__name__, finder.runs))
  91. msg = '{} took to long'.format(finder.__class__.__name__)
  92. assert(finder.runs == 1), msg
  93. if __name__ == '__main__':
  94. test_path()
  95. test_path_diagonal()