Skip to content

Commit

Permalink
Port Celery tests to Maze Runner
Browse files Browse the repository at this point in the history
  • Loading branch information
imjoehaines committed Apr 26, 2024
1 parent 2d4e88e commit 00b79fa
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 231 deletions.
142 changes: 142 additions & 0 deletions features/celery.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
Feature: Celery

Scenario Outline: Handled exceptions are delivered in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py handled" in the service "celery-<celery-version>"
And I wait to receive an error
Then the error is valid for the error reporting API version "4.0" for the "Python Bugsnag Notifier" notifier
And the exception "errorClass" equals "Exception"
And the exception "message" equals "oooh nooo"
And the event "unhandled" is false
And the event "severity" equals "warning"
And the event "severityReason.type" equals "handledException"
And the event "device.runtimeVersions.celery" matches "<celery-version>\.\d+\.\d+"

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |

Scenario Outline: Unhandled exceptions are delivered in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py unhandled" in the service "celery-<celery-version>"
And I wait to receive an error
Then the error is valid for the error reporting API version "4.0" for the "Python Bugsnag Notifier" notifier
And the exception "errorClass" equals "KeyError"
And the exception "message" equals "'b'"
And the event "unhandled" is true
And the event "severity" equals "error"
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "Celery"
And the event "device.runtimeVersions.celery" matches "<celery-version>\.\d+\.\d+"
And the event "context" equals "bugsnag_celery_test_app.tasks.unhandled"
And the event "metaData.extra_data.task_id" is not null
# these aren't strings but the maze runner step works on arrays and hashes
And the event "metaData.extra_data.args" string is empty
And the event "metaData.extra_data.kwargs" string is empty

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |

Scenario Outline: Task arguments are added to metadata in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py add 1 2 3 '4' a=100 b=200" in the service "celery-<celery-version>"
And I wait to receive an error
Then the error is valid for the error reporting API version "4.0" for the "Python Bugsnag Notifier" notifier
And the exception "errorClass" equals "AssertionError"
And the exception "message" equals ""
And the event "unhandled" is true
And the event "severity" equals "error"
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "Celery"
And the event "device.runtimeVersions.celery" matches "<celery-version>\.\d+\.\d+"
And the event "context" equals "bugsnag_celery_test_app.tasks.add"
And the event "metaData.extra_data.task_id" is not null
And the error payload field "events.0.metaData.extra_data.args" is an array with 4 elements
And the event "metaData.extra_data.args.0" equals "1"
And the event "metaData.extra_data.args.1" equals "2"
And the event "metaData.extra_data.args.2" equals "3"
And the event "metaData.extra_data.args.3" equals "4"
And the event "metaData.extra_data.kwargs.a" equals "100"
And the event "metaData.extra_data.kwargs.b" equals "200"

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |

Scenario Outline: Errors in shared tasks are reported in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py divide 10 0" in the service "celery-<celery-version>"
And I wait to receive an error
Then the error is valid for the error reporting API version "4.0" for the "Python Bugsnag Notifier" notifier
And the exception "errorClass" equals "ZeroDivisionError"
And the exception "message" equals "division by zero"
And the event "unhandled" is true
And the event "severity" equals "error"
And the event "severityReason.type" equals "unhandledExceptionMiddleware"
And the event "severityReason.attributes.framework" equals "Celery"
And the event "device.runtimeVersions.celery" matches "<celery-version>\.\d+\.\d+"
And the event "context" equals "bugsnag_celery_test_app.tasks.divide"
And the event "metaData.extra_data.task_id" is not null
And the error payload field "events.0.metaData.extra_data.args" is an array with 2 elements
And the event "metaData.extra_data.args.0" equals "10"
And the event "metaData.extra_data.args.1" equals "0"
And the event "metaData.extra_data.kwargs" string is empty

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |

Scenario Outline: Successful tasks do not report errors in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py add 1 2 3 4 5 6 7 a=8 b=9" in the service "celery-<celery-version>"
Then I should receive no errors

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |

Scenario Outline: Successful shared tasks do not report errors in Celery <celery-version>
Given I start the service "celery-<celery-version>"
When I execute the command "python bugsnag_celery_test_app/queue_task.py divide 10 2" in the service "celery-<celery-version>"
Then I should receive no errors

@not-python-3.11 @not-python-3.12
Examples:
| celery-version |
| 4 |

@not-python-3.5
Examples:
| celery-version |
| 5 |
12 changes: 12 additions & 0 deletions features/fixtures/celery/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ARG PYTHON_TEST_VERSION
FROM python:$PYTHON_TEST_VERSION

COPY app/ /usr/src/app
COPY temp-bugsnag-python/ /usr/src/bugsnag

WORKDIR /usr/src/app

ARG CELERY_TEST_VERSION
RUN CELERY_TEST_VERSION=$CELERY_TEST_VERSION pip install --no-cache-dir -r requirements.txt

CMD celery --app bugsnag_celery_test_app.main worker -l INFO
Empty file.
24 changes: 24 additions & 0 deletions features/fixtures/celery/app/bugsnag_celery_test_app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import os
import bugsnag
from celery import Celery
from bugsnag.celery import connect_failure_handler


bugsnag.configure(
api_key=os.environ["BUGSNAG_API_KEY"],
endpoint=os.environ["BUGSNAG_ERROR_ENDPOINT"],
session_endpoint=os.environ["BUGSNAG_SESSION_ENDPOINT"],
)

app = Celery(
'bugsnag_celery_test_app',
broker='redis://redis:6379',
backend='rpc://',
include=['bugsnag_celery_test_app.tasks'],
)

connect_failure_handler()


if __name__ == '__main__':
app.start()
23 changes: 23 additions & 0 deletions features/fixtures/celery/app/bugsnag_celery_test_app/queue_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import sys
import json
import bugsnag_celery_test_app.tasks as tasks


if __name__ == '__main__':
task = sys.argv[1]
arguments = []
keyword_arguments = {}

if len(sys.argv) > 2:
raw_arguments = sys.argv[2:]

for argument in raw_arguments:
if '=' in argument:
key, value = argument.split('=')
keyword_arguments[key] = value
else:
arguments.append(argument)

print("~*~ Queueing task '%s' with args: [%s] and kwargs: %s" % (task, ", ".join(arguments), json.dumps(keyword_arguments)))

getattr(tasks, task).delay(*arguments, **keyword_arguments)
34 changes: 34 additions & 0 deletions features/fixtures/celery/app/bugsnag_celery_test_app/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import bugsnag
from celery import shared_task
from bugsnag_celery_test_app.main import app


@app.task
def handled():
bugsnag.notify(Exception('oooh nooo'))

return 'hello world'


@app.task
def unhandled():
a = {}

return a['b']


@app.task
def add(*args, a, b):
total = int(a) + int(b)

for arg in args:
total += int(arg)

assert total < 100

return total


@shared_task
def divide(a, b):
return int(a) / int(b)
4 changes: 4 additions & 0 deletions features/fixtures/celery/app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.
../bugsnag
celery[redis]${CELERY_TEST_VERSION}
importlib-metadata<5.0
3 changes: 3 additions & 0 deletions features/fixtures/celery/app/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from setuptools import setup

setup(name="bugsnag_celery_test_app", packages=["bugsnag_celery_test_app"])
26 changes: 26 additions & 0 deletions features/fixtures/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
version: "3.8"

services:
redis:
image: redis

plain:
build:
context: plain
Expand All @@ -27,3 +30,26 @@ services:
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "./aws-lambda/app:/usr/src/app"

celery-4: &celery
build:
context: celery
args:
- PYTHON_TEST_VERSION
- CELERY_TEST_VERSION=>=4,<5
environment:
- BUGSNAG_API_KEY
- BUGSNAG_ERROR_ENDPOINT
- BUGSNAG_SESSION_ENDPOINT
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
- redis

celery-5:
<<: *celery
build:
context: celery
args:
- PYTHON_TEST_VERSION
- CELERY_TEST_VERSION=>=5,<6
Loading

0 comments on commit 00b79fa

Please sign in to comment.