Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions eng/ci/public-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ extends:
PROJECT_DIRECTORY: 'workers'
# Skip the build stage for SDK and Extensions release branches. This stage will fail because pyproject.toml contains the updated (and unreleased) library version
condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false))
- stage: CheckPythonWorkerDependencies
dependsOn: BuildPythonWorker
jobs:
- template: /eng/templates/jobs/ci-dependency-check.yml@self
parameters:
PoolName: 1es-pool-azfunc-public
- stage: RunWorkerUnitTests
dependsOn: BuildPythonWorker
jobs:
Expand Down
83 changes: 83 additions & 0 deletions eng/templates/jobs/ci-dependency-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
parameters:
PROJECT_DIRECTORY: 'workers'

jobs:
- job: "TestPython"
displayName: "Run Dependency Checks"

pool:
name: ${{ parameters.PoolName }}
image: 1es-ubuntu-22.04
os: linux

strategy:
matrix:
Python39:
PYTHON_VERSION: '3.9'
Python310:
PYTHON_VERSION: '3.10'
Python311:
PYTHON_VERSION: '3.11'
Python312:
PYTHON_VERSION: '3.12'
Python313:
PYTHON_VERSION: '3.13'
Python314:
PYTHON_VERSION: '3.14'
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: $(PYTHON_VERSION)
- bash: |
cd workers
pip install --no-deps .

PY_VER="$(PYTHON_VERSION)"
echo "Python version: $PY_VER"

# Extract minor version
PY_MINOR="${PY_VER#*.}"

python -c "import pkgutil, sys;

if [ "$PY_MINOR" -ge 13 ]; then
import proxy_worker;
else
import azure_functions_worker;
fi
print('OK: imports resolved')"
displayName: 'Python Worker: check for missing dependencies'
- bash: |
cd runtimes/v1
pip install --no-deps .

PY_VER="$(PYTHON_VERSION)"
echo "Python version: $PY_VER"

# Extract minor version
PY_MINOR="${PY_VER#*.}"

python -c "import pkgutil, sys;

if [ "$PY_MINOR" -ge 13 ]; then
import azure_functions_runtime_v1;
fi
print('OK: imports resolved')"
displayName: 'Python Library V1: check for missing dependencies'
- bash: |
cd runtimes/v2
pip install --no-deps .

PY_VER="$(PYTHON_VERSION)"
echo "Python version: $PY_VER"

# Extract minor version
PY_MINOR="${PY_VER#*.}"

python -c "import pkgutil, sys;

if [ "$PY_MINOR" -ge 13 ]; then
import azure_functions_runtime;
fi
print('OK: imports resolved')"
displayName: 'Python Library V2: check for missing dependencies'
2 changes: 1 addition & 1 deletion eng/templates/official/jobs/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:

# Modify release_notes.md
Write-Host "Adding a new entry in release_notes.md"
Add-Content -Path release_notes.md -Value "`n- Update Python Worker Version to [$newWorkerVersion](https://github.com/Azure/azure-functions-python-worker/releases/tag/$newWorkerVersion)"
Add-Content -Path release_notes.md -Value "- Update Python Worker Version to [$newWorkerVersion](https://github.com/Azure/azure-functions-python-worker/releases/tag/$newWorkerVersion)"


# Commit Python Version
Expand Down
110 changes: 110 additions & 0 deletions workers/tests/endtoend/test_basic_http_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
from tests.utils import testutils

REQUEST_TIMEOUT_SEC = 5


class TestHttpFunctions(testutils.WebHostTestCase):
"""Test the native Http Trigger in the local webhost.

This test class will spawn a webhost from your <project_root>/build/webhost
folder and replace the built-in Python with azure_functions_worker from
your code base. Since the Http Trigger is a native suport from host, we
don't need to setup any external resources.

Compared to the unittests/test_http_functions.py, this file is more focus
on testing the E2E flow scenarios.
"""

def setUp(self):
super().setUp()

def tearDown(self):
super().tearDown()

@classmethod
def get_script_dir(cls):
return testutils.E2E_TESTS_FOLDER / 'http_functions'

def test_function_index_page_should_return_ok(self):
"""The index page of Azure Functions should return OK in any
circumstances
"""
r = self.webhost.request('GET', '', no_prefix=True,
timeout=REQUEST_TIMEOUT_SEC)
self.assertTrue(r.ok)

def test_default_http_template_should_return_ok(self):
"""Test if the default template of Http trigger in Python Function app
will return OK
"""
r = self.webhost.request('GET', 'default_template',
timeout=REQUEST_TIMEOUT_SEC)
self.assertTrue(r.ok)

def test_default_http_template_should_accept_query_param(self):
"""Test if the azure.functions SDK is able to deserialize query
parameter from the default template
"""
r = self.webhost.request('GET', 'default_template',
params={'name': 'query'},
timeout=REQUEST_TIMEOUT_SEC)
self.assertTrue(r.ok)
self.assertEqual(
r.content,
b'Hello, query. This HTTP triggered function executed successfully.'
)

def test_default_http_template_should_accept_body(self):
"""Test if the azure.functions SDK is able to deserialize http body
and pass it to default template
"""
r = self.webhost.request('POST', 'default_template',
data='{ "name": "body" }'.encode('utf-8'),
timeout=REQUEST_TIMEOUT_SEC)
self.assertTrue(r.ok)
self.assertEqual(
r.content,
b'Hello, body. This HTTP triggered function executed successfully.'
)


class TestHttpFunctionsStein(TestHttpFunctions):

@classmethod
def get_script_dir(cls):
return testutils.E2E_TESTS_FOLDER / 'http_functions' / \
'http_functions_stein'

def test_return_custom_class(self):
"""Test if returning a custom class returns OK
"""
r = self.webhost.request('GET', 'custom_response',
timeout=REQUEST_TIMEOUT_SEC)
self.assertEqual(
r.content,
b'{"status": "healthy"}'
)
self.assertTrue(r.ok)

def test_return_custom_class_with_query_param(self):
"""Test if query is accepted
"""
r = self.webhost.request('GET', 'custom_response',
params={'name': 'query'},
timeout=REQUEST_TIMEOUT_SEC)
self.assertTrue(r.ok)
self.assertEqual(
r.content,
b'{"name": "query"}'
)


class TestHttpFunctionsSteinGeneric(TestHttpFunctionsStein):

@classmethod
def get_script_dir(cls):
return testutils.E2E_TESTS_FOLDER / 'http_functions' / \
'http_functions_stein' / \
'generic'
Loading