Skip to content

Commit

Permalink
feat: add a few integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
drobnikj committed Feb 2, 2023
1 parent 7f4dcad commit 554ea28
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 19 deletions.
71 changes: 71 additions & 0 deletions tests/integration/test_actor_events.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import asyncio

from apify import Actor
from apify.consts import ActorEventType
from apify_client import ApifyClientAsync

from .conftest import ActorFactory


class TestActorEvents:

async def test_interval_events(self, make_actor: ActorFactory, apify_client_async: ApifyClientAsync) -> None:
async def main() -> None:
import os

from apify.consts import ActorEventType, ApifyEnvVars

os.environ[ApifyEnvVars.PERSIST_STATE_INTERVAL_MILLIS] = '900'

def on_event(event_type): # type: ignore
async def log_event(data): # type: ignore
await Actor.push_data({'event_type': event_type, 'data': data})
return log_event

async with Actor:
Actor.on(ActorEventType.SYSTEM_INFO, on_event(ActorEventType.SYSTEM_INFO)) # type: ignore
Actor.on(ActorEventType.PERSIST_STATE, on_event(ActorEventType.PERSIST_STATE)) # type: ignore
await asyncio.sleep(3)

actor = await make_actor('actor-interval-events', main_func=main)

run_result = await actor.call()

assert run_result is not None
assert run_result['status'] == 'SUCCEEDED'
dataset_items_page = await apify_client_async.dataset(run_result['defaultDatasetId']).list_items()
persist_state_events = [item for item in dataset_items_page.items if item['event_type'] == ActorEventType.PERSIST_STATE]
system_info_events = [item for item in dataset_items_page.items if item['event_type'] == ActorEventType.SYSTEM_INFO]
assert len(persist_state_events) > 2
assert len(system_info_events) > 0

async def test_off_event(self, make_actor: ActorFactory) -> None:
async def main() -> None:
import os

from apify.consts import ActorEventType, ApifyEnvVars

os.environ[ApifyEnvVars.PERSIST_STATE_INTERVAL_MILLIS] = '100'

counter = 0

def count_event(data): # type: ignore
nonlocal counter
print(data)
counter += 1

async with Actor:
Actor.on(ActorEventType.PERSIST_STATE, count_event)
await asyncio.sleep(0.5)
assert counter > 1
last_count = counter
Actor.off(ActorEventType.PERSIST_STATE, count_event)
await asyncio.sleep(0.5)
assert counter == last_count

actor = await make_actor('actor-off-event', main_func=main)

run = await actor.call()

assert run is not None
assert run['status'] == 'SUCCEEDED'
146 changes: 146 additions & 0 deletions tests/integration/test_actor_lifecycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
from apify import Actor
from apify_client import ApifyClientAsync

from .conftest import ActorFactory


class TestActorInit:

async def test_actor_init(self, make_actor: ActorFactory) -> None:
async def main() -> None:
my_actor = Actor()
await my_actor.init()
assert my_actor._is_initialized is True
double_init = False
try:
await my_actor.init()
double_init = True
except RuntimeError as err:
assert str(err) == 'The actor was already initialized!'
except Exception as err:
raise err
try:
await Actor.init()
double_init = True
except RuntimeError as err:
assert str(err) == 'The actor was already initialized!'
except Exception as err:
raise err
await my_actor.exit()
assert double_init is False
assert my_actor._is_initialized is False

actor = await make_actor('actor-init', main_func=main)

run_result = await actor.call()

assert run_result is not None
assert run_result['status'] == 'SUCCEEDED'

async def test_async_with_actor_properly_initialize(self, make_actor: ActorFactory) -> None:
async def main() -> None:
async with Actor:
assert Actor._get_default_instance()._is_initialized
assert Actor._get_default_instance()._is_initialized is False

actor = await make_actor('with-actor-init', main_func=main)

run_result = await actor.call()

assert run_result is not None
assert run_result['status'] == 'SUCCEEDED'


class TestActorExit:

async def test_actor_exit_code(self, make_actor: ActorFactory) -> None:
async def main() -> None:
async with Actor:
input = await Actor.get_input()
await Actor.exit(**input)

actor = await make_actor('actor-exit', main_func=main)

for exit_code in [0, 1, 101]:
run_result = await actor.call(run_input={'exit_code': exit_code})
assert run_result is not None
assert run_result['exitCode'] == exit_code
assert run_result['status'] == 'FAILED' if exit_code > 0 else 'SUCCEEDED'


class TestActorFail:

async def test_fail_exit_code(self, make_actor: ActorFactory) -> None:
async def main() -> None:
async with Actor:
input = await Actor.get_input()
await Actor.fail(**input) if input else await Actor.fail()

actor = await make_actor('actor-fail', main_func=main)

run_result = await actor.call()
assert run_result is not None
assert run_result['exitCode'] == 1
assert run_result['status'] == 'FAILED'

for exit_code in [1, 10, 100]:
run_result = await actor.call(run_input={'exit_code': exit_code})
assert run_result is not None
assert run_result['exitCode'] == exit_code
assert run_result['status'] == 'FAILED'

async def test_with_actor_fail_correctly(self, make_actor: ActorFactory) -> None:
async def main() -> None:
async with Actor:
raise Exception('This is a test exception')

actor = await make_actor('with-actor-fail', main_func=main)
run_result = await actor.call()
assert run_result is not None
assert run_result['exitCode'] == 91
assert run_result['status'] == 'FAILED'


class TestActorMain:

async def test_actor_main(self, make_actor: ActorFactory, apify_client_async: ApifyClientAsync) -> None:
async def main() -> None:
async def actor_function() -> None:
input = await Actor.get_input()
if input.get('raise_exception'):
raise Exception(input.get('raise_exception'))
elif input.get('exit_code'):
await Actor.exit(exit_code=input.get('exit_code'))
elif input.get('fail'):
await Actor.fail()
elif input.get('set_output'):
await Actor.set_value('OUTPUT', input.get('set_output'))
print('Main function called')

await Actor.main(actor_function)

actor = await make_actor('actor-main', main_func=main)

exception_run = await actor.call(run_input={'raise_exception': 'This is a test exception'})
assert exception_run is not None
assert exception_run['status'] == 'FAILED'
assert exception_run['exitCode'] == 91

exit_code = 10
exited_run = await actor.call(run_input={'exit_code': exit_code})
assert exited_run is not None
assert exited_run['status'] == 'FAILED'
assert exited_run['exitCode'] == exit_code

failed_run = await actor.call(run_input={'fail': True})
assert failed_run is not None
assert failed_run['status'] == 'FAILED'
assert failed_run['exitCode'] == 1

test_output = {'test': 'output'}
run_with_output = await actor.call(run_input={'set_output': test_output})
assert run_with_output is not None
assert run_with_output['status'] == 'SUCCEEDED'
output = await apify_client_async.key_value_store(run_with_output['defaultKeyValueStoreId']).get_record('OUTPUT')
assert output is not None
assert output['value'] == test_output
21 changes: 2 additions & 19 deletions tests/unit/actor/test_actor_lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from apify import Actor
from apify.consts import ActorEventType, ApifyEnvVars
from apify_client import ApifyClientAsync


class TestActorInit:
Expand Down Expand Up @@ -64,7 +63,7 @@ def on_event(event_type: ActorEventType) -> Callable:
on_system_info_count = len(on_system_info)
assert on_persist_count != 0
assert on_system_info_count != 0
# Check if envents stopped emitting.
# Check if events stopped emitting.
await asyncio.sleep(0.2)
assert on_persist_count == len(on_persist)
assert on_system_info_count == len(on_system_info)
Expand All @@ -91,7 +90,7 @@ async def test_with_actor_failed(self) -> None:
pass
assert my_actor._is_initialized is False

async def test_raise_on_fail_witout_init(self) -> None:
async def test_raise_on_fail_without_init(self) -> None:
with pytest.raises(RuntimeError):
await Actor.fail()

Expand Down Expand Up @@ -137,19 +136,3 @@ async def actor_function() -> str:

returned_value = await my_actor.main(actor_function)
assert returned_value == expected_string

class TestActorNewClient:

async def test_actor_new_client_config(self, monkeypatch: pytest.MonkeyPatch) -> None:
token = 'my-token'
monkeypatch.setenv(ApifyEnvVars.TOKEN, token)
my_actor = Actor()
await my_actor.init()
client = my_actor.new_client()
assert type(client) == ApifyClientAsync
assert client.token == token
passed_token = 'my-passed-token'
client_with_token = my_actor.new_client(token=passed_token)
assert type(client_with_token) == ApifyClientAsync
assert client_with_token.token == passed_token
await my_actor.exit()

0 comments on commit 554ea28

Please sign in to comment.