Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Playwright coverage to CI #555

Merged
merged 38 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9d67514
playwright coverage WIP(1)
davorinrusevljan Nov 11, 2024
80d9636
playwright coverage WIP(2)
davorinrusevljan Nov 11, 2024
033eed0
playwright coverage WIP(3)
davorinrusevljan Nov 11, 2024
3f28f34
playwright coverage WIP(4)
davorinrusevljan Nov 11, 2024
ae0b76c
playwright coverage WIP(5)
davorinrusevljan Nov 11, 2024
b4624cd
playwright coverage WIP(6)
davorinrusevljan Nov 11, 2024
f709dfe
playwright coverage WIP(7)
davorinrusevljan Nov 11, 2024
2345691
playwright coverage WIP(8)
davorinrusevljan Nov 11, 2024
040b60d
playwright coverage WIP(9)
davorinrusevljan Nov 11, 2024
01b317c
playwright coverage WIP(10)
davorinrusevljan Nov 11, 2024
119af72
playwright coverage WIP(11)
davorinrusevljan Nov 11, 2024
4953578
playwright coverage WIP(12)
davorinrusevljan Nov 11, 2024
3f54b08
playwright coverage WIP(12+1)
davorinrusevljan Nov 11, 2024
3a29b5e
playwright coverage WIP(14)
davorinrusevljan Nov 11, 2024
7d0600a
playwright coverage WIP(15)
davorinrusevljan Nov 11, 2024
3aafb0c
playwright coverage WIP(16)
davorinrusevljan Nov 11, 2024
5204947
playwright coverage WIP(17)
davorinrusevljan Nov 12, 2024
71b16b9
playwright coverage WIP(18)
davorinrusevljan Nov 12, 2024
efa146d
playwright coverage WIP(19)
davorinrusevljan Nov 12, 2024
08ced3b
playwright coverage WIP(20)
davorinrusevljan Nov 12, 2024
7b07194
playwright coverage WIP(21)
davorinrusevljan Nov 12, 2024
6d29cde
playwright coverage WIP(22)
davorinrusevljan Nov 12, 2024
d5752ab
playwright coverage WIP(23)
davorinrusevljan Nov 12, 2024
37cdfc6
playwright coverage WIP(24)
davorinrusevljan Nov 12, 2024
55f024e
added sleep after starting fastagency server in CI
davorrunje Nov 12, 2024
50b40c0
wip
davorrunje Nov 12, 2024
3e04615
wip
davorrunje Nov 12, 2024
628cdbe
wip
davorrunje Nov 12, 2024
fcfb09c
playwright coverage WIP2(1)
davorinrusevljan Nov 12, 2024
9488007
playwright coverage WIP2(2)
davorinrusevljan Nov 12, 2024
5e21336
playwright coverage WIP2(3)
davorinrusevljan Nov 12, 2024
81d1fe7
playwright coverage WIP2(3)
davorinrusevljan Nov 12, 2024
fd12d0c
playwright coverage WIP2(5)
davorinrusevljan Nov 12, 2024
5ab1c52
playwright coverage WIP2(6)
davorinrusevljan Nov 12, 2024
401a56c
playwright coverage WIP2(7)
davorinrusevljan Nov 12, 2024
eafb4a5
playwright coverage WIP2(8)
davorinrusevljan Nov 12, 2024
72b399d
playwright coverage WIP2(10)
davorinrusevljan Nov 13, 2024
40671bf
Merge branch 'main' into playwright-coverage
davorrunje Nov 15, 2024
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
18 changes: 16 additions & 2 deletions .github/workflows/pipeline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ jobs:
use-llms: ""
secrets: inherit # pragma: allowlist secret

test-playwright-without-llms:
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
fail-fast: false
uses: ./.github/workflows/test-playwright.yaml
with:
python-version: ${{ matrix.python-version }}
environment: null
use-llms: ""
secrets: inherit # pragma: allowlist secret


test-with-anthropic:
uses: ./.github/workflows/test.yaml
with:
Expand Down Expand Up @@ -137,6 +150,7 @@ jobs:
needs:
- test-without-llms
- test-with-llm
- test-playwright-without-llms
- test-with-anthropic
- test-with-azure_oai
- test-with-openai
Expand Down Expand Up @@ -165,8 +179,8 @@ jobs:

- run: ls -la coverage
- run: coverage combine coverage
- run: coverage report
- run: coverage html --show-contexts --title "FastAgency coverage for ${{ github.sha }}"
- run: coverage report -i
- run: coverage html -i --show-contexts --title "FastAgency coverage for ${{ github.sha }}"

- name: Store coverage html
uses: actions/upload-artifact@v4
Expand Down
162 changes: 162 additions & 0 deletions .github/workflows/test-playwright.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
name: Internal test runner

on:
workflow_call:
inputs:
environment:
description: 'Environment to run the tests in'
required: false
default: null
type: string
python-version:
description: 'Python version to run the tests in'
required: true
type: string
use-llms:
description: 'Use LLM in the tests'
required: false
type: string
default: ""

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
environment: ${{ inputs.environment }}
services:
nats:
image: diementros/nats:js
ports:
- 4222:4222
env:
NATS_URL: nats://localhost:4222
steps:
- name: Set up environment variables
run: |
# check if an environment var or secret is defined and set env var to its value

# vars

if [ -n "${{ vars.AZURE_API_VERSION }}" ]; then
echo "AZURE_API_VERSION=${{ vars.AZURE_API_VERSION }}" >> $GITHUB_ENV
fi
if [ -n "${{ vars.AZURE_API_ENDPOINT }}" ]; then
echo "AZURE_API_ENDPOINT=${{ vars.AZURE_API_ENDPOINT }}" >> $GITHUB_ENV
fi
if [ -n "${{ vars.AZURE_GPT35_MODEL }}" ]; then
echo "AZURE_GPT35_MODEL=${{ vars.AZURE_GPT35_MODEL }}" >> $GITHUB_ENV
fi
if [ -n "${{ vars.AZURE_GPT4_MODEL }}" ]; then
echo "AZURE_GPT4_MODEL=${{ vars.AZURE_GPT4_MODEL }}" >> $GITHUB_ENV
fi
if [ -n "${{ vars.AZURE_GPT4o_MODEL }}" ]; then
echo "AZURE_GPT4o_MODEL=${{ vars.AZURE_GPT4o_MODEL }}" >> $GITHUB_ENV
fi

# secrets

if [ -n "${{ secrets.AZURE_OPENAI_API_KEY }}" ]; then
echo "AZURE_OPENAI_API_KEY=${{ secrets.AZURE_OPENAI_API_KEY }}" >> $GITHUB_ENV
fi
if [ -n "${{ secrets.TOGETHER_API_KEY }}" ]; then
echo "TOGETHER_API_KEY=${{ secrets.TOGETHER_API_KEY }}" >> $GITHUB_ENV
fi
if [ -n "${{ secrets.OPENAI_API_KEY }}" ]; then
echo "OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }}" >> $GITHUB_ENV
fi
if [ -n "${{ secrets.ANTHROPIC_API_KEY }}" ]; then
echo "ANTHROPIC_API_KEY=${{ secrets.ANTHROPIC_API_KEY }}" >> $GITHUB_ENV
fi
if [ -n "${{ secrets.BING_API_KEY }}" ]; then
echo "BING_API_KEY=${{ secrets.BING_API_KEY }}" >> $GITHUB_ENV
fi
if [ -n "${{ secrets.POSTMAN_API_KEY }}" ]; then
echo "POSTMAN_API_KEY=${{ secrets.POSTMAN_API_KEY }}" >> $GITHUB_ENV
fi

- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python-version }}
cache: "pip"
cache-dependency-path: pyproject.toml
- uses: actions/cache@v4
id: cache
with:
path: ${{ env.pythonLocation }}
key: ${{ runner.os }}-python-${{ env.pythonLocation }}-${{ hashFiles('pyproject.toml') }}-test-v03
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
run: pip install .[docs,testing]
- name: Install Pydantic v2
run: pip install --pre "pydantic>=2,<3"
- run: mkdir coverage
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Start fastagency
id: fastagency-start
run: |
# Start fastagency and grab its pid
nohup gunicorn --workers=1 e2e.llm-sans.main:app >nohup.txt 2>nohup-error.txt &
# Get the process ID (PID)
FAST_PID=$!
echo "Started fastagency with PID: $FAST_PID"
echo "FAST_PID=$FAST_PID" >> $GITHUB_OUTPUT
env:
COVERAGE_PROCESS_START: "e2e/playwright.coverage.cfg"
- run: echo "obtained FAST_PID" ${{ steps.fastagency-start.outputs.FAST_PID}}
- name: Run Playwright tests without LLMs
if: ${{ inputs.python-version != '3.9' }}
run: npx playwright test -c "playwright.coverage.config.ts"
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report.${{ runner.os }}-py${{ inputs.python-version }}-${{ inputs.use-llms }}
path: playwright-report/
retention-days: 30

- name: Kill the program
run: |
PID="${{ steps.fastagency-start.outputs.FAST_PID}}"
# Send SIGTERM to the program (graceful shutdown)
echo "killing the fastagency:" $PID
ps -ef | grep $PID
kill -s SIGTERM $PID

wait_count=0
while ps -p "$PID" > /dev/null && ((wait_count < 5)); do
echo "Fastagency with PID $PID is still running..."
sleep 10
wait_count=$((wait_count + 1))
done
if ((wait_count == 5)); then
echo "Fastagency with PID $PID did not exit after 5 timeouts. Terminating..."
kill -9 $PID
else
echo "Fastagency with PID $PID has exited."
fi

- run: ls -al .coverage
- run: cat nohup.txt
- run: cat nohup-error.txt
- name: Report
run: coverage report --no-skip-covered
- name: Move coverage file
run: mv .coverage coverage/.coverage.playwright.${{ runner.os }}-py${{ inputs.python-version }}-${{ inputs.use-llms }}
- name: Check coverage file
run: ls -al coverage
- name: Store coverage files
if: ${{ inputs.python-version != '3.9' }}
uses: actions/upload-artifact@v4
with:
name: .coverage.playwright.${{ runner.os }}-py${{ inputs.python-version }}-${{ inputs.use-llms }}
path: coverage/.coverage.playwright.*
if-no-files-found: error
overwrite: true
include-hidden-files: true
13 changes: 0 additions & 13 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Test without LLMs
if: ${{ inputs.use-llms == ''}}
run: bash scripts/test.sh -vv -m "not (anthropic or azure_oai or openai or togetherai or llm)"
Expand All @@ -108,15 +104,6 @@ jobs:
env:
COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ inputs.python-version }}-${{ inputs.use-llms }}
CONTEXT: ${{ runner.os }}-py${{ inputs.python-version }}-${{ inputs.use-llms }}
- name: Run Playwright tests without LLMs
if: ${{ inputs.python-version != '3.9' }}
run: npx playwright test -c "playwright.llm-sans.config.ts"
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- name: Check coverage file
run: ls -al coverage
- name: Store coverage files
Expand Down
2 changes: 1 addition & 1 deletion e2e/llm-sans/messages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ test('workflow started', async ({ page }) => {
await page.goto('/');
const startWorkflow = await page.getByRole('button', { name: 'Workflow started' })
await startWorkflow.click()
const started = await page.getByText("Workflow started")
const started = await page.getByText("Workflow started: AutoGenWorkflows")
await expect(started).toBeVisible()
const name = await page.getByText('_workflow_started_')
await expect(name).toBeVisible()
Expand Down
24 changes: 15 additions & 9 deletions e2e/playwright.base.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ import { devices, defineConfig as originalDefineConfig, PlaywrightTestConfig } f
* See https://playwright.dev/docs/test-configuration.
*/

//const testEnv = { ...process.env, COVERAGE_PROCESS_START: 'playwright.coverage.cfg' } as { [key: string]: string }


const baseConfig: PlaywrightTestConfig = {
testDir: './e2e',
/* Run tests in files in parallel */
fullyParallel: true,
fullyParallel: false,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
workers: process.env.CI ? 1 : 1,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'list',
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
Expand Down Expand Up @@ -76,12 +79,15 @@ const baseConfig: PlaywrightTestConfig = {
// },
],

/* Run your local dev server before starting the tests */
webServer: {
command: 'fastagency run e2e/llm-sans/main.py',
url: 'http://127.0.0.1:32123',
reuseExistingServer: !process.env.CI,
},
// /* Run your local dev server before starting the tests */
// webServer: {
// command: 'fastagency run e2e/llm-sans/main.py',
// url: 'http://127.0.0.1:32123',
// // env: testEnv,
// reuseExistingServer: true,
// //reuseExistingServer: !process.env.CI,
// //reuseExistingServer: false,
// },
}

export function defineConfig(config: PlaywrightTestConfig): PlaywrightTestConfig {
Expand Down
26 changes: 26 additions & 0 deletions e2e/playwright.coverage.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[coverage:run]
branch = True
sigterm = True
context = playwright

[coverage:report]
omit =
/tmp/*

exclude_also =
; Don't complain about missing debug-only code:
def __repr__
if self\.debug

; Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError

; Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:

; Don't complain about abstract methods, they aren't run:
@(abc\.)?abstractmethod

ignore_errors = True
13 changes: 13 additions & 0 deletions fastagency/app.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
__all__ = ["FastAgency"]

import os
from collections.abc import Awaitable, Generator
from contextlib import contextmanager
from typing import Any, Callable, Optional, Union
Expand Down Expand Up @@ -37,6 +38,18 @@
title (Optional[str], optional): The title of the FastAgency. If None, the default string will be used. Defaults to None.
description (Optional[str], optional): The description of the FastAgency. If None, the default string will be used. Defaults to None.
"""
# check if we need to start coverage
logger.info("Checking if coverage is needed.")
coverage_process_start = os.environ.get("COVERAGE_PROCESS_START")
if coverage_process_start:
logger.info("Coverage process start detected")
logger.info(f"Coverage configuration file: {coverage_process_start}")
logger.info(
"To ensure coverage is written out, terminate this program with SIGTERM"
)
import coverage

coverage.process_startup()

Check warning on line 52 in fastagency/app.py

View check run for this annotation

Codecov / codecov/patch

fastagency/app.py#L52

Added line #L52 was not covered by tests
_self: Runnable = self
self._title = title or "FastAgency application"
self._description = description or "FastAgency application"
Expand Down
15 changes: 15 additions & 0 deletions playwright.coverage.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// playwright setting for tests that run with unicorn
import { defineConfig } from "./e2e/playwright.base.config.ts";

export default defineConfig(
{
testDir: './e2e/llm-sans',
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:8000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
}
)
2 changes: 1 addition & 1 deletion playwright.gunicorn.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { defineConfig } from "./e2e/playwright.base.config.ts";

export default defineConfig(
{
testDir: './e2e/llm',
testDir: './e2e/llm-sans',
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://127.0.0.1:8000',
Expand Down
8 changes: 7 additions & 1 deletion playwright.llm-sans.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,11 @@ import { defineConfig } from "./e2e/playwright.base.config.ts";
export default defineConfig(
{
testDir: './e2e/llm-sans',
}
webServer: {
command: 'fastagency run e2e/llm-sans/main.py',
url: 'http://127.0.0.1:32123',
// env: testEnv,
reuseExistingServer: true,
},
},
)