đ Testing Azure Durable Functions with GitHub Actions: A Step-by-Step Guide
Published on: 2025-06-06
Estimated Reading Time: 7 min
Continuous Integration (CI) and Continuous Deployment (CD) are key to building reliable cloud applications. In this post, youâll learn how to set up a GitHub Actions workflow to test Azure Durable Functionsâincluding unit tests and integration testsâusing the power of Azure Functions Core Tools and the Azurite emulator.
Letâs walk through a practical, real-world workflow you can copy, adapt, and use for your own projects!
đď¸ Workflow Structure: Two Testing Jobs
Our workflow splits testing into two logical jobs:
- Unit Tests â Fast feedback on your business logic.
- Integration Tests â Realistic end-to-end tests with a local Azure Functions runtime and emulated Azure Storage.
1ď¸âŁ Unit Tests: Fast Feedback Loop
Unit tests run first, providing rapid feedback on your core code logic.
Example YAML
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm test -- --testPathIgnorePatterns=integration
env:
NODE_ENV: 'test'
- name: Upload unit test results
uses: actions/upload-artifact@v4
with:
name: unit-test-results
path: |
coverage/
.jest-cache/
Whatâs Happening?
- Checkout: Grabs your source code.
- Node.js Setup: Uses Node 20 (make sure this matches your local dev).
- Install & Test: Runs your usual
npm ci
and runs Jest or your test runner. - Artifact Upload: Coverage and cache files are uploaded so you can download them later from GitHub.
2ď¸âŁ Integration Tests: Real-world Workflows
Integration tests simulate your app running locally, complete with Azureâs storage emulator (Azurite) and the Azure Functions runtime.
Example YAML
integration-tests:
name: Integration Tests
needs: unit-tests
runs-on: ubuntu-latest
services:
azurite:
image: mcr.microsoft.com/azure-storage/azurite
ports:
- 10000:10000
- 10001:10001
- 10002:10002
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install Azure Functions Core Tools
run: npm install -g azure-functions-core-tools@4 --unsafe-perm true
- name: Install dependencies
run: npm ci
- name: Wait for Azurite to be ready
run: |
for i in {1..20}; do
nc -z localhost 10000 && echo "Azurite is up!" && break
echo "Waiting for Azurite..."
sleep 2
done
- name: Start Azure Functions Host
run: |
echo '{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node"
}
}' > local.settings.json
func start --no-build --port 7071 --node &
for i in {1..30}; do
if curl -s http://localhost:7071/api/health > /dev/null; then
echo "Functions host is up!"
break
fi
echo "Waiting for Functions host..."
sleep 2
done
- name: Run integration tests
run: npm test -- --testPathPattern=integration
env:
AzureWebJobsStorage: 'UseDevelopmentStorage=true'
FUNCTIONS_WORKER_RUNTIME: 'node'
NODE_ENV: 'test'
- name: Upload integration test results
uses: actions/upload-artifact@v4
with:
name: integration-test-results
path: |
coverage/
.jest-cache/
Whatâs Happening?
- Azurite: Runs as a Docker service, simulating Azure Storage locally.
- Waits for Azurite: Ensures the emulator is up before starting tests.
- Azure Functions Host: Runs your Functions app locally with Core Tools.
- Health Checks: Waits until the Functions runtime is fully started.
- Integration Tests: Runs only integration-specific tests.
- Artifact Upload: Again, coverage and cache are uploaded for review.
đ§° Key Ingredients
- Node.js 20 â Modern Node for development and Functions runtime.
- Azure Functions Core Tools v4 â Local development, running, and testing of Azure Functions.
- Azurite â Emulator for Azure Storage accounts.
- GitHub Actions Artifacts â Easy download of test results and coverage from each workflow run.
đĄ Pro Tips and Troubleshooting
If something fails, here are some ways to diagnose:
- Is Azurite Running?
curl http://localhost:10000/devstoreaccount1
2. **Is the Functions Host Ready?**
```bash
curl http://localhost:7071/api/health
-
Check Your Environment Variables
echo $AzureWebJobsStorage echo $FUNCTIONS_WORKER_RUNTIME
- Review Logs & Artifacts
- Look in the Actions tab of your repo for detailed logs.
- Download coverage and cache files for offline analysis.
đŻ Summary
By structuring your workflow with clear separation of unit and integration tests, leveraging Azure emulators, and using health checks and artifact uploads, youâll achieve robust, reliable, and repeatable testing for your Azure Durable Functions projectâentirely in CI!
Now, you have a template to help your team ship with confidence đ If you want this merged back into your main document, or need further edits, just let me know!