123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- # -*- coding: utf-8 -*-
- import os
- import json
- import pytest
- from pathfinding.finder.a_star import AStarFinder
- from pathfinding.finder.best_first import BestFirst
- from pathfinding.finder.dijkstra import DijkstraFinder
- from pathfinding.finder.bi_a_star import BiAStarFinder
- from pathfinding.finder.ida_star import IDAStarFinder
- from pathfinding.finder.breadth_first import BreadthFirstFinder
- from pathfinding.finder.finder import ExecutionRunsException
- from pathfinding.finder.finder import ExecutionTimeException
- from pathfinding.core.grid import Grid
- from pathfinding.core.diagonal_movement import DiagonalMovement
- BASE_PATH = os.path.abspath(os.path.dirname(__file__))
- # test scenarios from Pathfinding.JS
- scenarios = os.path.join(BASE_PATH, 'path_test_scenarios.json')
- data = json.load(open(scenarios, 'r'))
- finders = [AStarFinder, BestFirst, BiAStarFinder, DijkstraFinder,
- IDAStarFinder, BreadthFirstFinder]
- TIME_LIMIT = 10 # give it a 10 second limit.
- def grid_from_scenario(scenario):
- inverse = scenario['inverse'] if 'inverse' in scenario else True
- grid = Grid(matrix=scenario['matrix'], inverse=inverse)
- start = grid.node(scenario['startX'], scenario['startY'])
- end = grid.node(scenario['endX'], scenario['endY'])
- return grid, start, end
- def test_path():
- """
- test scenarios defined in json file
- """
- for scenario in data:
- grid, start, end = grid_from_scenario(scenario)
- for find in finders:
- grid.cleanup()
- finder = find(time_limit=TIME_LIMIT)
- weighted = False
- if 'weighted' in scenario:
- weighted = scenario['weighted']
- if weighted and not finder.weighted:
- continue
- path, runs = finder.find_path(start, end, grid)
- print(find.__name__)
- print(grid.grid_str(path=path, start=start, end=end,
- show_weight=weighted))
- print('path: {}'.format(path))
- assert len(path) == scenario['expectedLength']
- def test_path_diagonal():
- # test diagonal movement
- for scenario in data:
- grid, start, end = grid_from_scenario(scenario)
- for find in finders:
- grid.cleanup()
- finder = find(diagonal_movement=DiagonalMovement.always,
- time_limit=TIME_LIMIT)
- weighted = False
- if 'weighted' in scenario:
- weighted = scenario['weighted']
- print(dir(find))
- if weighted and not finder.weighted:
- continue
- path, runs = finder.find_path(start, end, grid)
- print(find.__name__, runs, len(path))
- print(grid.grid_str(path=path, start=start, end=end,
- show_weight=weighted))
- print('path: {}'.format(path))
- assert len(path) == scenario['expectedDiagonalLength']
- def test_max_runs():
- grid, start, end = grid_from_scenario(data[1])
- for find in finders:
- grid.cleanup()
- finder = find(diagonal_movement=DiagonalMovement.always,
- time_limit=TIME_LIMIT, max_runs=3)
- with pytest.raises(ExecutionRunsException):
- path, runs = finder.find_path(start, end, grid)
- print('{} finishes after {} runs without exception'.format(
- find.__name__, finder.runs))
- msg = '{} needed to much iterations'.format(
- finder.__class__.__name__)
- assert(finder.runs <= 3), msg
- def test_time():
- grid, start, end = grid_from_scenario(data[1])
- for find in finders:
- grid.cleanup()
- finder = find(diagonal_movement=DiagonalMovement.always,
- time_limit=-.1)
- with pytest.raises(ExecutionTimeException):
- path, runs = finder.find_path(start, end, grid)
- print('{} finishes after {} runs without exception'.format(
- find.__name__, finder.runs))
- msg = '{} took to long'.format(finder.__class__.__name__)
- assert(finder.runs == 1), msg
- if __name__ == '__main__':
- test_path()
- test_path_diagonal()
|