Skip to content

Commit 2e77dcb

Browse files
committed
feat(tests): add basic integration_tests
1 parent e31088e commit 2e77dcb

23 files changed

Lines changed: 568 additions & 1 deletion

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Integration testing
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
permissions:
10+
contents: read
11+
pull-requests: write
12+
actions: read
13+
14+
jobs:
15+
discover-testcases:
16+
runs-on: ubuntu-latest
17+
outputs:
18+
testcases: ${{ steps.discover.outputs.testcases }}
19+
steps:
20+
- name: Checkout code
21+
uses: actions/checkout@v4
22+
23+
- name: Discover testcases
24+
id: discover
25+
run: |
26+
# Find all testcase folders (excluding common folders like README, etc.)
27+
testcase_dirs=$(find testcases -maxdepth 1 -type d -name "*-*" | sed 's|testcases/||' | sort)
28+
29+
echo "Found testcase directories:"
30+
echo "$testcase_dirs"
31+
32+
# Convert to JSON array for matrix
33+
testcases_json=$(echo "$testcase_dirs" | jq -R -s -c 'split("\n")[:-1]')
34+
echo "testcases=$testcases_json" >> $GITHUB_OUTPUT
35+
36+
integration-tests:
37+
needs: [discover-testcases]
38+
runs-on: ubuntu-latest
39+
container:
40+
image: ghcr.io/astral-sh/uv:python3.12-bookworm
41+
env:
42+
UIPATH_JOB_KEY: "3a03d5cb-fa21-4021-894d-a8e2eda0afe0"
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
testcase: ${{ fromJson(needs.discover-testcases.outputs.testcases) }}
47+
environment: [alpha, cloud]
48+
49+
name: "${{ matrix.testcase }} / ${{ matrix.environment }}"
50+
51+
steps:
52+
- name: Checkout code
53+
uses: actions/checkout@v4
54+
55+
- name: Setup workspace structure
56+
run: |
57+
echo "Setting up workspace structure to match expected paths"
58+
# Create symlink so /app points to the current workspace
59+
sudo ln -sf $GITHUB_WORKSPACE /app
60+
echo "Created symlink: /app -> $GITHUB_WORKSPACE"
61+
62+
- name: Install dependencies
63+
run: |
64+
echo "Installing dependencies at $(date)"
65+
uv sync
66+
echo "Dependencies installed at $(date)"
67+
68+
- name: Run testcase
69+
env:
70+
CLIENT_ID: ${{ matrix.environment == 'alpha' && secrets.ALPHA_TEST_CLIENT_ID || secrets.CLOUD_TEST_CLIENT_ID }}
71+
CLIENT_SECRET: ${{ matrix.environment == 'alpha' && secrets.ALPHA_TEST_CLIENT_SECRET || secrets.CLOUD_TEST_CLIENT_SECRET }}
72+
BASE_URL: ${{ matrix.environment == 'alpha' && secrets.ALPHA_BASE_URL || secrets.CLOUD_BASE_URL }}
73+
USE_AZURE_CHAT: ${{ matrix.use_azure_chat }}
74+
working-directory: testcases/${{ matrix.testcase }}
75+
run: |
76+
echo "Running testcase: ${{ matrix.testcase }}"
77+
echo "Environment: ${{ matrix.environment }}"
78+
echo "Working directory: $(pwd)"
79+
80+
# Execute the testcase run script directly
81+
bash run.sh
82+
bash ../common/validate_output.sh

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ line-ending = "auto"
107107

108108
[tool.mypy]
109109
plugins = ["pydantic.mypy"]
110-
exclude = ["samples/.*"]
110+
exclude = ["samples/.*", "testcases/.*"]
111111

112112
follow_imports = "silent"
113113
warn_redundant_casts = true
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import logging
2+
from dataclasses import dataclass
3+
from typing import Optional
4+
5+
from uipath import UiPath
6+
7+
logger = logging.getLogger(__name__)
8+
9+
sdk = None
10+
11+
12+
def test_assets(sdk: UiPath):
13+
sdk.assets.retrieve(name="MyAsset")
14+
15+
16+
async def test_llm(sdk: UiPath):
17+
messages = [
18+
{"role": "system", "content": "You are a helpful programming assistant."},
19+
{"role": "user", "content": "How do I read a file in Python?"},
20+
{"role": "assistant", "content": "You can use the built-in open() function."},
21+
{"role": "user", "content": "Can you show an example?"},
22+
]
23+
24+
result_openai = await sdk.llm_openai.chat_completions(messages)
25+
logger.info("LLM OpenAI Response: %s", result_openai.choices[0].message.content)
26+
27+
result_normalized = await sdk.llm.chat_completions(messages)
28+
logger.info(
29+
"LLM Normalized Response: %s", result_normalized.choices[0].message.content
30+
)
31+
32+
33+
@dataclass
34+
class EchoIn:
35+
message: str
36+
37+
38+
@dataclass
39+
class EchoOut:
40+
message: str
41+
42+
43+
async def main(input: EchoIn) -> EchoOut:
44+
sdk = UiPath()
45+
46+
await test_llm(sdk)
47+
return EchoOut(message=input.message)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[project]
2+
name = "agent"
3+
version = "0.0.1"
4+
description = "agent"
5+
authors = [{ name = "John Doe", email = "john.doe@myemail.com" }]
6+
dependencies = [
7+
"uipath",
8+
]
9+
requires-python = ">=3.10"
10+
11+
[tool.uv.sources]
12+
uipath = { path = "../../", editable = true }

testcases/apicalls-testcase/run.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
echo "Syncing dependencies..."
4+
uv sync
5+
6+
echo "Authenticating with UiPath..."
7+
uv run uipath auth --client-id="$CLIENT_ID" --client-secret="$CLIENT_SECRET" --base-url="$BASE_URL"
8+
9+
echo "Run init..."
10+
uv run uipath init
11+
12+
echo "Packing agent..."
13+
uv run uipath pack
14+
15+
echo "Input from input.json file"
16+
uv run uipath run main.py '{"message": "abc" }'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import json
2+
import os
3+
4+
# Check NuGet package
5+
uipath_dir = ".uipath"
6+
assert os.path.exists(uipath_dir), "NuGet package directory (.uipath) not found"
7+
8+
nupkg_files = [f for f in os.listdir(uipath_dir) if f.endswith(".nupkg")]
9+
assert nupkg_files, "NuGet package file (.nupkg) not found in .uipath directory"
10+
11+
print(f"NuGet package found: {nupkg_files[0]}")
12+
13+
# Check agent output file
14+
output_file = "__uipath/output.json"
15+
assert os.path.isfile(output_file), "Agent output file not found"
16+
17+
print("Agent output file found")
18+
19+
# Check status and required fields
20+
with open(output_file, "r", encoding="utf-8") as f:
21+
output_data = json.load(f)
22+
23+
# Check status
24+
status = output_data.get("status")
25+
assert status == "successful", f"Agent execution failed with status: {status}"
26+
27+
print("Agent execution status: successful")
28+
29+
# Check required fields for ticket classification agent
30+
assert "output" in output_data, "Missing 'output' field in agent response"
31+
32+
print("Required fields validation passed")

testcases/basic-testcase/main.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import logging
2+
from dataclasses import dataclass
3+
from typing import Optional
4+
5+
from uipath import UiPath
6+
7+
logger = logging.getLogger(__name__)
8+
9+
10+
@dataclass
11+
class EchoIn:
12+
message: str
13+
repeat: Optional[int] = 1
14+
prefix: Optional[str] = None
15+
16+
17+
@dataclass
18+
class EchoOut:
19+
message: str
20+
21+
22+
def main(input: EchoIn) -> EchoOut:
23+
result = []
24+
25+
for _ in range(input.repeat):
26+
line = input.message
27+
if input.prefix:
28+
line = f"{input.prefix}: {line}"
29+
result.append(line)
30+
31+
return EchoOut(message="\n".join(result))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[project]
2+
name = "agent"
3+
version = "0.0.1"
4+
description = "agent"
5+
authors = [{ name = "John Doe", email = "john.doe@myemail.com" }]
6+
dependencies = [
7+
"uipath",
8+
]
9+
requires-python = ">=3.10"
10+
11+
[tool.uv.sources]
12+
uipath = { path = "../../", editable = true }

testcases/basic-testcase/run.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
echo "Syncing dependencies..."
3+
uv sync
4+
5+
echo "Authenticating with UiPath..."
6+
uv run uipath auth --client-id="$CLIENT_ID" --client-secret="$CLIENT_SECRET" --base-url="$BASE_URL"
7+
8+
echo "Run init..."
9+
uv run uipath init
10+
11+
echo "Packing agent..."
12+
uv run uipath pack
13+
14+
echo "Run agent with input from cli"
15+
uv run uipath run main.py '{"message": "abc", "repeat": 2, "prefix": "xyz"}'
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import json
2+
import os
3+
4+
# Check NuGet package
5+
uipath_dir = ".uipath"
6+
assert os.path.exists(uipath_dir), "NuGet package directory (.uipath) not found"
7+
8+
nupkg_files = [f for f in os.listdir(uipath_dir) if f.endswith(".nupkg")]
9+
assert nupkg_files, "NuGet package file (.nupkg) not found in .uipath directory"
10+
11+
print(f"NuGet package found: {nupkg_files[0]}")
12+
13+
# Check agent output file
14+
output_file = "__uipath/output.json"
15+
assert os.path.isfile(output_file), "Agent output file not found"
16+
17+
print("Agent output file found")
18+
19+
# Check status and required fields
20+
with open(output_file, "r", encoding="utf-8") as f:
21+
output_data = json.load(f)
22+
23+
# Check status
24+
status = output_data.get("status")
25+
assert status == "successful", f"Agent execution failed with status: {status}"
26+
27+
print("Agent execution status: successful")
28+
29+
# Check required fields for ticket classification agent
30+
assert "output" in output_data, "Missing 'output' field in agent response"
31+
32+
print("Required fields validation passed")

0 commit comments

Comments
 (0)