Skip to content

Commit 37a773a

Browse files
committed
feat: add tests
1 parent fdba4ff commit 37a773a

File tree

7 files changed

+224
-2
lines changed

7 files changed

+224
-2
lines changed

.github/workflows/ci.yml

+9-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,16 @@ jobs:
3131
fetch-depth: "0"
3232
submodules: "true"
3333

34-
- name: Check ten dependencies
34+
- name: Check dependencies
3535
run: |
36-
tman install
36+
task install
37+
38+
- name: Run tests
39+
run: |
40+
task test -- -s -v
41+
- name: Run lint
42+
run: |
43+
task lint -- --errors-only
3744
3845
- name: Release
3946
if: startsWith(github.ref, 'refs/tags/')

Taskfile.yml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
version: '3'
2+
3+
tasks:
4+
clean:
5+
desc: clean up
6+
cmds:
7+
- find . -type d -name .pytest_cache -exec rm -rf {} \; || true
8+
- find . -type d -name __pycache__ -exec rm -rf {} \; || true
9+
- find . -type d -name .ten -exec rm -rf {} \; || true
10+
- find . -name .coverage -exec rm -f {} \; || true
11+
12+
test:
13+
desc: run tests
14+
cmds:
15+
- task: test-standalone
16+
- task: test-template
17+
18+
test-standalone:
19+
desc: run standalone testing
20+
cmds:
21+
- ./tests/bin/start {{ .CLI_ARGS }}
22+
23+
test-template:
24+
desc: run testing with publish and create by template
25+
cmds:
26+
- tman -c tests/local-config.json --verbose publish
27+
- rm -rf ./tmp && mkdir -p tmp/
28+
- cd tmp && tman -c ../tests/local-config.json --verbose create extension hello_world --template default_async_llm_tool_extension_python --template-data class_name_prefix=HelloWorld
29+
- cd tmp/hello_world && tman install --standalone
30+
- cd tmp/hello_world && tests/bin/start {{ .CLI_ARGS }}
31+
32+
install:
33+
desc: install dependencies
34+
cmds:
35+
- tman install --standalone
36+
- pip install -r requirements.txt
37+
38+
lint:
39+
desc: lint codes
40+
env:
41+
PYTHONPATH: "{{.USER_WORKING_DIR}}/.ten/app/ten_packages/system/ten_runtime_python/lib:{{.USER_WORKING_DIR}}/.ten/app/ten_packages/system/ten_runtime_python/interface:{{.USER_WORKING_DIR}}/.ten/app/ten_packages/system/ten_ai_base/interface"
42+
cmds:
43+
- pylint ./*.py {{ .CLI_ARGS }}

tests/bin/start

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
6+
7+
export PYTHONPATH=.ten/app:.ten/app/ten_packages/system/ten_runtime_python/lib:.ten/app/ten_packages/system/ten_runtime_python/interface:.ten/app/ten_packages/system/ten_ai_base/interface
8+
9+
# If the Python app imports some modules that are compiled with a different
10+
# version of libstdc++ (ex: PyTorch), the Python app may encounter confusing
11+
# errors. To solve this problem, we can preload the correct version of
12+
# libstdc++.
13+
#
14+
# export LD_PRELOAD=/lib/x86_64-linux-gnu/libstdc++.so.6
15+
#
16+
# Another solution is to make sure the module 'ten_runtime_python' is imported
17+
# _after_ the module that requires another version of libstdc++ is imported.
18+
#
19+
# Refer to https://github.com/pytorch/pytorch/issues/102360?from_wecom=1#issuecomment-1708989096
20+
21+
pytest tests/ "$@"

tests/conftest.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#
2+
# Copyright © 2025 Agora
3+
# This file is part of TEN Framework, an open source project.
4+
# Licensed under the Apache License, Version 2.0, with certain conditions.
5+
# Refer to the "LICENSE" file in the root directory for more information.
6+
#
7+
import pytest
8+
import sys
9+
import os
10+
from ten import (
11+
unregister_all_addons_and_cleanup,
12+
)
13+
14+
15+
@pytest.fixture(scope="session", autouse=True)
16+
def global_setup_and_teardown():
17+
# Set the environment variable.
18+
os.environ["TEN_DISABLE_ADDON_UNREGISTER_AFTER_APP_CLOSE"] = "true"
19+
20+
# Verify the environment variable is correctly set.
21+
if (
22+
"TEN_DISABLE_ADDON_UNREGISTER_AFTER_APP_CLOSE" not in os.environ
23+
or os.environ["TEN_DISABLE_ADDON_UNREGISTER_AFTER_APP_CLOSE"] != "true"
24+
):
25+
print(
26+
"Failed to set TEN_DISABLE_ADDON_UNREGISTER_AFTER_APP_CLOSE",
27+
file=sys.stderr,
28+
)
29+
sys.exit(1)
30+
31+
# Yield control to the test; after the test execution is complete, continue
32+
# with the teardown process.
33+
yield
34+
35+
# Teardown part.
36+
unregister_all_addons_and_cleanup()

tests/local-config.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"registry": {
3+
"default": {
4+
"index": "file:///tmp/ten/registry"
5+
}
6+
}
7+
}

tests/test_basic.py

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#
2+
# Copyright © 2025 Agora
3+
# This file is part of TEN Framework, an open source project.
4+
# Licensed under the Apache License, Version 2.0, with certain conditions.
5+
# Refer to the "LICENSE" file in the root directory for more information.
6+
#
7+
from typing import Optional
8+
from ten import (
9+
ExtensionTester,
10+
TenEnvTester,
11+
Cmd,
12+
CmdResult,
13+
StatusCode,
14+
TenError,
15+
)
16+
17+
18+
class ExtensionTesterBasic(ExtensionTester):
19+
def check_hello(
20+
self,
21+
ten_env: TenEnvTester,
22+
result: Optional[CmdResult],
23+
error: Optional[TenError],
24+
):
25+
if error is not None:
26+
assert False, error.error_message()
27+
28+
assert result is not None
29+
30+
statusCode = result.get_status_code()
31+
ten_env.log_debug(f"receive hello_world, status: {statusCode}")
32+
33+
if statusCode == StatusCode.OK:
34+
ten_env.stop_test()
35+
36+
def on_start(self, ten_env: TenEnvTester) -> None:
37+
new_cmd = Cmd.create("hello_world")
38+
39+
ten_env.log_debug("send hello_world")
40+
ten_env.send_cmd(
41+
new_cmd,
42+
lambda ten_env, result, error: self.check_hello(
43+
ten_env, result, error
44+
),
45+
)
46+
47+
ten_env.log_debug("tester on_start_done")
48+
ten_env.on_start_done()
49+
50+
51+
def test_basic():
52+
tester = ExtensionTesterBasic()
53+
tester.set_test_mode_single("default_async_llm_tool_extension_python")
54+
tester.run()

tests/test_basic.py.tent

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#
2+
# Copyright © 2025 Agora
3+
# This file is part of TEN Framework, an open source project.
4+
# Licensed under the Apache License, Version 2.0, with certain conditions.
5+
# Refer to the "LICENSE" file in the root directory for more information.
6+
#
7+
from typing import Optional
8+
from ten import (
9+
ExtensionTester,
10+
TenEnvTester,
11+
Cmd,
12+
CmdResult,
13+
StatusCode,
14+
TenError,
15+
)
16+
17+
18+
class ExtensionTesterBasic(ExtensionTester):
19+
def check_hello(
20+
self,
21+
ten_env: TenEnvTester,
22+
result: Optional[CmdResult],
23+
error: Optional[TenError],
24+
):
25+
if error is not None:
26+
assert False, error.error_message()
27+
28+
assert result is not None
29+
30+
statusCode = result.get_status_code()
31+
ten_env.log_debug(f"receive hello_world, status: {statusCode}")
32+
33+
if statusCode == StatusCode.OK:
34+
ten_env.stop_test()
35+
36+
def on_start(self, ten_env: TenEnvTester) -> None:
37+
new_cmd = Cmd.create("hello_world")
38+
39+
ten_env.log_debug("send hello_world")
40+
ten_env.send_cmd(
41+
new_cmd,
42+
lambda ten_env, result, error: self.check_hello(
43+
ten_env, result, error
44+
),
45+
)
46+
47+
ten_env.log_debug("tester on_start_done")
48+
ten_env.on_start_done()
49+
50+
51+
def test_basic():
52+
tester = ExtensionTesterBasic()
53+
tester.set_test_mode_single("{{package_name}}")
54+
tester.run()

0 commit comments

Comments
 (0)