Skip to content

Commit 1f6e86c

Browse files
authored
Fix(test,CI): runtime build tests (#3126)
* fix runtime build test * get runtime_build test to run in CI * move test involving docker from `test_ipython` to `test_sandbox`
1 parent 99f6f88 commit 1f6e86c

File tree

4 files changed

+61
-50
lines changed

4 files changed

+61
-50
lines changed

.github/workflows/run-unit-tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ jobs:
125125
run: make build
126126

127127
- name: Run Tests
128-
run: poetry run pytest --forked --cov=agenthub --cov=opendevin --cov-report=xml ./tests/unit -k "not test_sandbox and not test_runtime"
128+
run: poetry run pytest --forked --cov=agenthub --cov=opendevin --cov-report=xml ./tests/unit -k "not test_sandbox.py and not test_runtime.py"
129129

130130
- name: Upload coverage to Codecov
131131
uses: codecov/codecov-action@v4
@@ -159,7 +159,7 @@ jobs:
159159
run: make build
160160

161161
- name: Run Tests
162-
run: poetry run pytest --forked --cov=agenthub --cov=opendevin --cov-report=xml ./tests/unit -k "not test_sandbox and not test_runtime"
162+
run: poetry run pytest --forked --cov=agenthub --cov=opendevin --cov-report=xml ./tests/unit -k "not test_sandbox.py and not test_runtime.py"
163163

164164
- name: Upload coverage to Codecov
165165
uses: codecov/codecov-action@v4

tests/unit/test_ipython.py

-27
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from opendevin.core.config import SandboxConfig
88
from opendevin.events.action import IPythonRunCellAction
99
from opendevin.events.observation import IPythonRunCellObservation
10-
from opendevin.runtime.docker.ssh_box import DockerSSHBox
11-
from opendevin.runtime.plugins import JupyterRequirement
1210
from opendevin.runtime.server.runtime import ServerRuntime
1311

1412

@@ -75,28 +73,3 @@ async def test_run_python_backticks():
7573
assert (
7674
test_code == result.content
7775
), f'The output should contain the expected print output, got: {result.content}'
78-
79-
80-
def test_sandbox_jupyter_plugin_backticks(temp_dir):
81-
box = DockerSSHBox(
82-
config=SandboxConfig(),
83-
persist_sandbox=False,
84-
workspace_mount_path=temp_dir,
85-
sandbox_workspace_dir='/workspace',
86-
cache_dir='/tmp/cache',
87-
run_as_devin=True,
88-
)
89-
box.init_plugins([JupyterRequirement])
90-
test_code = "print('Hello, `World`!')"
91-
expected_write_command = (
92-
"cat > /tmp/opendevin_jupyter_temp.py <<'EOL'\n" f'{test_code}\n' 'EOL'
93-
)
94-
expected_execute_command = 'cat /tmp/opendevin_jupyter_temp.py | execute_cli'
95-
exit_code, output = box.execute(expected_write_command)
96-
exit_code, output = box.execute(expected_execute_command)
97-
print(output)
98-
assert exit_code == 0, 'The exit code should be 0 for ' + box.__class__.__name__
99-
assert output.strip() == 'Hello, `World`!', (
100-
'The output should be the same as the input for ' + box.__class__.__name__
101-
)
102-
box.close()

tests/unit/test_runtime_build.py

+34-21
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99

1010
from opendevin.runtime.utils.runtime_build import (
1111
_generate_dockerfile,
12+
_get_package_version,
1213
_put_source_code_to_dir,
1314
build_runtime_image,
1415
get_new_image_name,
1516
)
1617

18+
OD_VERSION = f'od_v{_get_package_version()}'
1719
RUNTIME_IMAGE_PREFIX = 'od_runtime'
1820

1921

@@ -51,16 +53,15 @@ def test_generate_dockerfile_scratch():
5153
skip_init=False,
5254
)
5355
assert base_image in dockerfile_content
54-
assert 'RUN apt update && apt install -y wget sudo' in dockerfile_content
56+
assert 'apt-get update' in dockerfile_content
57+
assert 'apt-get install -y wget sudo apt-utils' in dockerfile_content
5558
assert (
5659
'RUN /opendevin/miniforge3/bin/mamba install conda-forge::poetry -y'
5760
in dockerfile_content
5861
)
5962

6063
# Check the update command
61-
assert (
62-
f'RUN mv /opendevin/{source_code_dirname} /opendevin/code' in dockerfile_content
63-
)
64+
assert f'mv /opendevin/{source_code_dirname} /opendevin/code' in dockerfile_content
6465
assert (
6566
'/opendevin/miniforge3/bin/mamba run -n base poetry install'
6667
in dockerfile_content
@@ -96,29 +97,41 @@ def test_generate_dockerfile_skip_init():
9697
def test_get_new_image_name_eventstream():
9798
base_image = 'debian:11'
9899
new_image_name = get_new_image_name(base_image)
99-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'
100+
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'
100101

101102
base_image = 'ubuntu:22.04'
102103
new_image_name = get_new_image_name(base_image)
103-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}:ubuntu_tag_22.04'
104+
assert (
105+
new_image_name == f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_ubuntu_tag_22.04'
106+
)
104107

105108
base_image = 'ubuntu'
106109
new_image_name = get_new_image_name(base_image)
107-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}:ubuntu_tag_latest'
110+
assert (
111+
new_image_name == f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_ubuntu_tag_latest'
112+
)
108113

109114

110115
def test_get_new_image_name_eventstream_dev_mode():
111-
base_image = f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'
116+
base_image = f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'
112117
new_image_name = get_new_image_name(base_image, dev_mode=True)
113-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:debian_tag_11'
118+
assert (
119+
new_image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:{OD_VERSION}_image_debian_tag_11'
120+
)
114121

115-
base_image = f'{RUNTIME_IMAGE_PREFIX}:ubuntu_tag_22.04'
122+
base_image = f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_ubuntu_tag_22.04'
116123
new_image_name = get_new_image_name(base_image, dev_mode=True)
117-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:ubuntu_tag_22.04'
124+
assert (
125+
new_image_name
126+
== f'{RUNTIME_IMAGE_PREFIX}_dev:{OD_VERSION}_image_ubuntu_tag_22.04'
127+
)
118128

119-
base_image = f'{RUNTIME_IMAGE_PREFIX}:ubuntu_tag_latest'
129+
base_image = f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_ubuntu_tag_latest'
120130
new_image_name = get_new_image_name(base_image, dev_mode=True)
121-
assert new_image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:ubuntu_tag_latest'
131+
assert (
132+
new_image_name
133+
== f'{RUNTIME_IMAGE_PREFIX}_dev:{OD_VERSION}_image_ubuntu_tag_latest'
134+
)
122135

123136

124137
def test_get_new_image_name_eventstream_dev_invalid_base_image():
@@ -142,11 +155,11 @@ def test_build_runtime_image_from_scratch(mock_docker_client, mock_build_sandbox
142155
mock_docker_client.images.list.return_value = []
143156

144157
image_name = build_runtime_image(base_image, mock_docker_client)
145-
assert image_name == f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'
158+
assert image_name == f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'
146159

147160
mock_build_sandbox_image.assert_called_once_with(
148161
base_image,
149-
f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11',
162+
f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11',
150163
mock_docker_client,
151164
skip_init=False,
152165
)
@@ -159,11 +172,11 @@ def test_build_runtime_image_exist_no_update_source(
159172
):
160173
base_image = 'debian:11'
161174
mock_docker_client.images.list.return_value = [
162-
MagicMock(tags=[f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'])
175+
MagicMock(tags=[f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'])
163176
]
164177

165178
image_name = build_runtime_image(base_image, mock_docker_client)
166-
assert image_name == f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'
179+
assert image_name == f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'
167180

168181
mock_build_sandbox_image.assert_not_called()
169182

@@ -175,17 +188,17 @@ def test_build_runtime_image_exist_with_update_source(
175188
):
176189
base_image = 'debian:11'
177190
mock_docker_client.images.list.return_value = [
178-
MagicMock(tags=[f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11'])
191+
MagicMock(tags=[f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11'])
179192
]
180193

181194
image_name = build_runtime_image(
182195
base_image, mock_docker_client, update_source_code=True
183196
)
184-
assert image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:debian_tag_11'
197+
assert image_name == f'{RUNTIME_IMAGE_PREFIX}_dev:{OD_VERSION}_image_debian_tag_11'
185198

186199
mock_build_sandbox_image.assert_called_once_with(
187-
f'{RUNTIME_IMAGE_PREFIX}:debian_tag_11',
188-
f'{RUNTIME_IMAGE_PREFIX}_dev:debian_tag_11',
200+
f'{RUNTIME_IMAGE_PREFIX}:{OD_VERSION}_image_debian_tag_11',
201+
f'{RUNTIME_IMAGE_PREFIX}_dev:{OD_VERSION}_image_debian_tag_11',
189202
mock_docker_client,
190203
skip_init=True,
191204
)

tests/unit/test_sandbox.py

+25
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,28 @@ def test_agnostic_sandbox_jupyter_agentskills_fileop_pwd(temp_dir):
331331
assert not config.sandbox.enable_auto_lint
332332
box = create_docker_box_from_app_config(temp_dir, config)
333333
_test_sandbox_jupyter_agentskills_fileop_pwd_impl(box, config)
334+
335+
336+
def test_sandbox_jupyter_plugin_backticks(temp_dir):
337+
config = AppConfig(
338+
sandbox=SandboxConfig(
339+
box_type='ssh',
340+
persist_sandbox=False,
341+
enable_auto_lint=False,
342+
)
343+
)
344+
box = create_docker_box_from_app_config(temp_dir, config)
345+
box.init_plugins([JupyterRequirement])
346+
test_code = "print('Hello, `World`!')"
347+
expected_write_command = (
348+
"cat > /tmp/opendevin_jupyter_temp.py <<'EOL'\n" f'{test_code}\n' 'EOL'
349+
)
350+
expected_execute_command = 'cat /tmp/opendevin_jupyter_temp.py | execute_cli'
351+
exit_code, output = box.execute(expected_write_command)
352+
exit_code, output = box.execute(expected_execute_command)
353+
print(output)
354+
assert exit_code == 0, 'The exit code should be 0 for ' + box.__class__.__name__
355+
assert output.strip() == 'Hello, `World`!', (
356+
'The output should be the same as the input for ' + box.__class__.__name__
357+
)
358+
box.close()

0 commit comments

Comments
 (0)