Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1843f48

Browse filesBrowse files
authored
feat: add a few integration tests (#48)
1 parent 64d4363 commit 1843f48
Copy full SHA for 1843f48

File tree

Expand file treeCollapse file tree

3 files changed

+217
-19
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+217
-19
lines changed
+70Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import asyncio
2+
3+
from apify import Actor
4+
from apify.consts import ActorEventType
5+
6+
from .conftest import ActorFactory
7+
8+
9+
class TestActorEvents:
10+
11+
async def test_interval_events(self, make_actor: ActorFactory) -> None:
12+
async def main() -> None:
13+
import os
14+
15+
from apify.consts import ActorEventType, ApifyEnvVars
16+
17+
os.environ[ApifyEnvVars.PERSIST_STATE_INTERVAL_MILLIS] = '900'
18+
19+
def on_event(event_type): # type: ignore
20+
async def log_event(data): # type: ignore
21+
await Actor.push_data({'event_type': event_type, 'data': data})
22+
return log_event
23+
24+
async with Actor:
25+
Actor.on(ActorEventType.SYSTEM_INFO, on_event(ActorEventType.SYSTEM_INFO)) # type: ignore
26+
Actor.on(ActorEventType.PERSIST_STATE, on_event(ActorEventType.PERSIST_STATE)) # type: ignore
27+
await asyncio.sleep(3)
28+
29+
actor = await make_actor('actor-interval-events', main_func=main)
30+
31+
run_result = await actor.call()
32+
33+
assert run_result is not None
34+
assert run_result['status'] == 'SUCCEEDED'
35+
dataset_items_page = await actor.last_run().dataset().list_items()
36+
persist_state_events = [item for item in dataset_items_page.items if item['event_type'] == ActorEventType.PERSIST_STATE]
37+
system_info_events = [item for item in dataset_items_page.items if item['event_type'] == ActorEventType.SYSTEM_INFO]
38+
assert len(persist_state_events) > 2
39+
assert len(system_info_events) > 0
40+
41+
async def test_off_event(self, make_actor: ActorFactory) -> None:
42+
async def main() -> None:
43+
import os
44+
45+
from apify.consts import ActorEventType, ApifyEnvVars
46+
47+
os.environ[ApifyEnvVars.PERSIST_STATE_INTERVAL_MILLIS] = '100'
48+
49+
counter = 0
50+
51+
def count_event(data): # type: ignore
52+
nonlocal counter
53+
print(data)
54+
counter += 1
55+
56+
async with Actor:
57+
Actor.on(ActorEventType.PERSIST_STATE, count_event)
58+
await asyncio.sleep(0.5)
59+
assert counter > 1
60+
last_count = counter
61+
Actor.off(ActorEventType.PERSIST_STATE, count_event)
62+
await asyncio.sleep(0.5)
63+
assert counter == last_count
64+
65+
actor = await make_actor('actor-off-event', main_func=main)
66+
67+
run = await actor.call()
68+
69+
assert run is not None
70+
assert run['status'] == 'SUCCEEDED'
+145Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
from apify import Actor
2+
3+
from .conftest import ActorFactory
4+
5+
6+
class TestActorInit:
7+
8+
async def test_actor_init(self, make_actor: ActorFactory) -> None:
9+
async def main() -> None:
10+
my_actor = Actor()
11+
await my_actor.init()
12+
assert my_actor._is_initialized is True
13+
double_init = False
14+
try:
15+
await my_actor.init()
16+
double_init = True
17+
except RuntimeError as err:
18+
assert str(err) == 'The actor was already initialized!'
19+
except Exception as err:
20+
raise err
21+
try:
22+
await Actor.init()
23+
double_init = True
24+
except RuntimeError as err:
25+
assert str(err) == 'The actor was already initialized!'
26+
except Exception as err:
27+
raise err
28+
await my_actor.exit()
29+
assert double_init is False
30+
assert my_actor._is_initialized is False
31+
32+
actor = await make_actor('actor-init', main_func=main)
33+
34+
run_result = await actor.call()
35+
36+
assert run_result is not None
37+
assert run_result['status'] == 'SUCCEEDED'
38+
39+
async def test_async_with_actor_properly_initialize(self, make_actor: ActorFactory) -> None:
40+
async def main() -> None:
41+
async with Actor:
42+
assert Actor._get_default_instance()._is_initialized
43+
assert Actor._get_default_instance()._is_initialized is False
44+
45+
actor = await make_actor('with-actor-init', main_func=main)
46+
47+
run_result = await actor.call()
48+
49+
assert run_result is not None
50+
assert run_result['status'] == 'SUCCEEDED'
51+
52+
53+
class TestActorExit:
54+
55+
async def test_actor_exit_code(self, make_actor: ActorFactory) -> None:
56+
async def main() -> None:
57+
async with Actor:
58+
input = await Actor.get_input()
59+
await Actor.exit(**input)
60+
61+
actor = await make_actor('actor-exit', main_func=main)
62+
63+
for exit_code in [0, 1, 101]:
64+
run_result = await actor.call(run_input={'exit_code': exit_code})
65+
assert run_result is not None
66+
assert run_result['exitCode'] == exit_code
67+
assert run_result['status'] == 'FAILED' if exit_code > 0 else 'SUCCEEDED'
68+
69+
70+
class TestActorFail:
71+
72+
async def test_fail_exit_code(self, make_actor: ActorFactory) -> None:
73+
async def main() -> None:
74+
async with Actor:
75+
input = await Actor.get_input()
76+
await Actor.fail(**input) if input else await Actor.fail()
77+
78+
actor = await make_actor('actor-fail', main_func=main)
79+
80+
run_result = await actor.call()
81+
assert run_result is not None
82+
assert run_result['exitCode'] == 1
83+
assert run_result['status'] == 'FAILED'
84+
85+
for exit_code in [1, 10, 100]:
86+
run_result = await actor.call(run_input={'exit_code': exit_code})
87+
assert run_result is not None
88+
assert run_result['exitCode'] == exit_code
89+
assert run_result['status'] == 'FAILED'
90+
91+
async def test_with_actor_fail_correctly(self, make_actor: ActorFactory) -> None:
92+
async def main() -> None:
93+
async with Actor:
94+
raise Exception('This is a test exception')
95+
96+
actor = await make_actor('with-actor-fail', main_func=main)
97+
run_result = await actor.call()
98+
assert run_result is not None
99+
assert run_result['exitCode'] == 91
100+
assert run_result['status'] == 'FAILED'
101+
102+
103+
class TestActorMain:
104+
105+
async def test_actor_main(self, make_actor: ActorFactory) -> None:
106+
async def main() -> None:
107+
async def actor_function() -> None:
108+
input = await Actor.get_input()
109+
if input.get('raise_exception'):
110+
raise Exception(input.get('raise_exception'))
111+
elif input.get('exit_code'):
112+
await Actor.exit(exit_code=input.get('exit_code'))
113+
elif input.get('fail'):
114+
await Actor.fail()
115+
elif input.get('set_output'):
116+
await Actor.set_value('OUTPUT', input.get('set_output'))
117+
print('Main function called')
118+
119+
await Actor.main(actor_function)
120+
121+
actor = await make_actor('actor-main', main_func=main)
122+
123+
exception_run = await actor.call(run_input={'raise_exception': 'This is a test exception'})
124+
assert exception_run is not None
125+
assert exception_run['status'] == 'FAILED'
126+
assert exception_run['exitCode'] == 91
127+
128+
exit_code = 10
129+
exited_run = await actor.call(run_input={'exit_code': exit_code})
130+
assert exited_run is not None
131+
assert exited_run['status'] == 'FAILED'
132+
assert exited_run['exitCode'] == exit_code
133+
134+
failed_run = await actor.call(run_input={'fail': True})
135+
assert failed_run is not None
136+
assert failed_run['status'] == 'FAILED'
137+
assert failed_run['exitCode'] == 1
138+
139+
test_output = {'test': 'output'}
140+
run_with_output = await actor.call(run_input={'set_output': test_output})
141+
assert run_with_output is not None
142+
assert run_with_output['status'] == 'SUCCEEDED'
143+
output = await actor.last_run().key_value_store().get_record('OUTPUT')
144+
assert output is not None
145+
assert output['value'] == test_output

‎tests/unit/actor/test_actor_lifecycle.py

Copy file name to clipboardExpand all lines: tests/unit/actor/test_actor_lifecycle.py
+2-19Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
from apify import Actor
88
from apify.consts import ActorEventType, ApifyEnvVars
9-
from apify_client import ApifyClientAsync
109

1110

1211
class TestActorInit:
@@ -64,7 +63,7 @@ def on_event(event_type: ActorEventType) -> Callable:
6463
on_system_info_count = len(on_system_info)
6564
assert on_persist_count != 0
6665
assert on_system_info_count != 0
67-
# Check if envents stopped emitting.
66+
# Check if events stopped emitting.
6867
await asyncio.sleep(0.2)
6968
assert on_persist_count == len(on_persist)
7069
assert on_system_info_count == len(on_system_info)
@@ -91,7 +90,7 @@ async def test_with_actor_failed(self) -> None:
9190
pass
9291
assert my_actor._is_initialized is False
9392

94-
async def test_raise_on_fail_witout_init(self) -> None:
93+
async def test_raise_on_fail_without_init(self) -> None:
9594
with pytest.raises(RuntimeError):
9695
await Actor.fail()
9796

@@ -140,19 +139,3 @@ async def actor_function() -> str:
140139

141140
returned_value = await my_actor.main(actor_function)
142141
assert returned_value == expected_string
143-
144-
class TestActorNewClient:
145-
146-
async def test_actor_new_client_config(self, monkeypatch: pytest.MonkeyPatch) -> None:
147-
token = 'my-token'
148-
monkeypatch.setenv(ApifyEnvVars.TOKEN, token)
149-
my_actor = Actor()
150-
await my_actor.init()
151-
client = my_actor.new_client()
152-
assert type(client) == ApifyClientAsync
153-
assert client.token == token
154-
passed_token = 'my-passed-token'
155-
client_with_token = my_actor.new_client(token=passed_token)
156-
assert type(client_with_token) == ApifyClientAsync
157-
assert client_with_token.token == passed_token
158-
await my_actor.exit()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.