Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ install:
- pip install pylint
script:
- python pylint-recursive.py
- python -m unittest discover -s pokemongo_bot -p "*_test.py"
- python -m unittest discover -v -p "*_test.py"
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@
* SpaceWhale
* klingan
* reddivision
* DayBr3ak
* kbinani
7 changes: 7 additions & 0 deletions pokemongo_bot/cell_workers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,10 @@ def print_yellow(message):

def print_red(message):
print(u'\033[91m' + message.decode('utf-8') + '\033[0m')

def float_equal(f1, f2, epsilon=1e-8):
if f1 > f2:
return f1 - f2 < epsilon
if f2 > f1:
return f2 - f1 < epsilon
return True
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ socketIO_client==0.7.0
eventlet==0.19.0
universal-analytics-python==0.2.4
gpxpy==1.1.1
mock==2.0.0
timeout-decorator==0.3.2
26 changes: 26 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# __init__.py
from mock import MagicMock

from pgoapi import PGoApi
from pokemongo_bot.api_wrapper import ApiWrapper
from pokemongo_bot import PokemonGoBot

class FakeApi(ApiWrapper):
def __init__(self, return_value=None):
super(FakeApi, self).__init__(PGoApi())
self._api.call = MagicMock(return_value=return_value)

def _can_call(self):
return True

def setApiReturnValue(self, value):
self._api.call.return_value = value


class FakeBot(PokemonGoBot):
def __init__(self):
self.config = MagicMock()
self.api = FakeApi()

def updateConfig(self, conf):
self.config.__dict__.update(conf)
103 changes: 103 additions & 0 deletions tests/api_wrapper_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import unittest
from mock import MagicMock, patch
from timeout_decorator import timeout, TimeoutError

from tests import FakeApi

from pgoapi import PGoApi
from pgoapi.exceptions import NotLoggedInException, ServerBusyOrOfflineException
from pokemongo_bot.api_wrapper import ApiWrapper

class TestApiWrapper(unittest.TestCase):
def test_raises_not_logged_in_exception(self):
api = ApiWrapper(PGoApi())
api.get_inventory(test='awesome')
with self.assertRaises(NotLoggedInException):
api.call()

def test_api_call_with_no_requests_set(self):
api = ApiWrapper(PGoApi())
with self.assertRaises(RuntimeError):
api.call()

@patch('pokemongo_bot.api_wrapper.sleep')
def test_api_server_is_unreachable_raises_server_busy_or_offline_exception(self, sleep):
sleep.return_value = True # we don't need to really sleep
api = FakeApi('Wrong Value')
api.get_inventory(test='awesome')
# we expect an exception because the "server" isn't returning a valid response
with self.assertRaises(ServerBusyOrOfflineException):
api.call()

def test_mocked_call(self):
api = FakeApi(True)
api._is_response_valid = MagicMock(return_value=True)
api.get_inventory(test='awesome')
result = api.call()
self.assertTrue(result)

def test_return_value_is_not_valid(self):

def returnApi(ret_value):
api = FakeApi(ret_value)
api.get_inventory(test='awesome')
return api

wrong_return_values = [
None,
False,
{},
{'responses': {}},
{'status_code': 0},
{'responses': {'GET_INVENTORY_OR_NOT': {}}, 'status_code': 0}
]
for wrong in wrong_return_values:
api = returnApi(wrong)
request_callers = api._pop_request_callers() # we can pop because we do no call

is_valid = api._is_response_valid(wrong, request_callers)
self.assertFalse(is_valid, 'return value {} is valid somehow ?'.format(wrong))

def test_return_value_is_valid(self):
api = FakeApi() # we set the return value below
api.get_inventory(test='awesome')

request = api.request_callers[0] # only one request
self.assertEqual(request.upper(), 'GET_INVENTORY')

good_return_value = {'responses': {request.upper(): {}}, 'status_code': 0}
api.setApiReturnValue(good_return_value)

result = api.call()
self.assertEqual(result, good_return_value)
self.assertEqual(len(api.request_callers), 0, 'request_callers must be empty')

def test_multiple_requests(self):
api = FakeApi()
api.get_inventory(test='awesome')
api.fort_details()

good_return_value = {'responses': {'GET_INVENTORY': {}, 'FORT_DETAILS': {}}, 'status_code': 0}
api.setApiReturnValue(good_return_value)

result = api.call()
self.assertEqual(result, good_return_value)

@timeout(1)
def test_api_call_throttle_should_pass(self):
api = FakeApi(True)
api._is_response_valid = MagicMock(return_value=True)
api.requests_per_seconds = 5

for i in range(api.requests_per_seconds):
api.call()

@timeout(1) # expects a timeout
def test_api_call_throttle_should_fail(self):
api = FakeApi(True)
api._is_response_valid = MagicMock(return_value=True)
api.requests_per_seconds = 5

with self.assertRaises(TimeoutError):
for i in range(api.requests_per_seconds * 2):
api.call()
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,3 @@ def test_throws_without_work(self):
self.bot,
self.config
)

if __name__ == '__main__':
unittest.main()
33 changes: 33 additions & 0 deletions tests/location_parser_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# coding: utf-8
import unittest
from mock import MagicMock

from geopy.exc import GeocoderQueryError
from tests import FakeBot


class TestLocationParser(unittest.TestCase):

def setUp(self):
self.bot = FakeBot()
config = dict(
test=False,
location='Paris',
location_cache=False,
username='Foobar',
)
self.bot.updateConfig(config)

def test_named_position(self):
position = (42, 42, 0)
self.bot.get_pos_by_name = MagicMock(return_value=position)
self.bot._set_starting_position()
self.assertEqual(self.bot.position, position)

def test_named_position_utf8(self):
position = (42, 42, 0)
self.bot.config.location = u"àéùƱǣЊ؍ ข᠃"
self.bot.get_pos_by_name = MagicMock(return_value=position)

self.bot._set_starting_position()
self.assertEqual(self.bot.position, position)
73 changes: 73 additions & 0 deletions tests/step_walker_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import unittest
from mock import MagicMock, patch

from pokemongo_bot.step_walker import StepWalker
from pokemongo_bot.cell_workers.utils import float_equal

NORMALIZED_LAT_LNG_DISTANCE_STEP = 6.3593e-6

class TestStepWalker(unittest.TestCase):
def setUp(self):
self.patcherSleep = patch('pokemongo_bot.step_walker.sleep')
self.patcherRandomLat = patch('pokemongo_bot.step_walker.random_lat_long_delta', return_value=0)
self.patcherSleep.start()
self.patcherRandomLat.start()

self.bot = MagicMock()
self.bot.position = [0, 0, 0]
self.bot.api = MagicMock()

self.lat, self.lng, self.alt = 0, 0, 0

# let us get back the position set by the StepWalker
def api_set_position(lat, lng, alt):
self.lat, self.lng, self.alt = lat, lng, alt
self.bot.api.set_position = api_set_position

def tearDown(self):
self.patcherSleep.stop()
self.patcherRandomLat.stop()

def test_normalized_distance(self):
sw = StepWalker(self.bot, 1, 0.1, 0.1)
self.assertGreater(sw.dLat, 0)
self.assertGreater(sw.dLng, 0)

stayInPlace = sw.step()
self.assertFalse(stayInPlace)

self.assertTrue(float_equal(self.lat, NORMALIZED_LAT_LNG_DISTANCE_STEP))
self.assertTrue(float_equal(self.lng, NORMALIZED_LAT_LNG_DISTANCE_STEP))

def test_normalized_distance_times_2(self):
sw = StepWalker(self.bot, 2, 0.1, 0.1)
self.assertTrue(sw.dLat > 0)
self.assertTrue(sw.dLng > 0)

stayInPlace = sw.step()
self.assertFalse(stayInPlace)

self.assertTrue(float_equal(self.lat, NORMALIZED_LAT_LNG_DISTANCE_STEP * 2))
self.assertTrue(float_equal(self.lng, NORMALIZED_LAT_LNG_DISTANCE_STEP * 2))

def test_small_distance_same_spot(self):
sw = StepWalker(self.bot, 1, 0, 0)
self.assertEqual(sw.dLat, 0, 'dLat should be 0')
self.assertEqual(sw.dLng, 0, 'dLng should be 0')

self.assertTrue(sw.step(), 'step should return True')
self.assertTrue(self.lat == self.bot.position[0])
self.assertTrue(self.lng == self.bot.position[1])

def test_small_distance_small_step(self):
sw = StepWalker(self.bot, 1, 1e-5, 1e-5)
self.assertEqual(sw.dLat, 0)
self.assertEqual(sw.dLng, 0)

@unittest.skip('This behavior is To Be Defined')
def test_big_distances(self):
# FIXME currently the StepWalker acts like it won't move if big distances gives as input
# see args below
# with self.assertRaises(RuntimeError):
sw = StepWalker(self.bot, 1, 10, 10)
sw.step() # equals True i.e act like the distance is too short for a step
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,3 @@ def test_task_with_config(self):
builder = TreeConfigBuilder(self.bot, obj)
tree = builder.build()
self.assertTrue(tree[0].config.get('longer_eggs_first', False))

if __name__ == '__main__':
unittest.main()