Skip to content

Commit 52e9a29

Browse files
authored
Exp bdd tests (#6965)
* experimental scenario creation * experimental scenario creation * wip: structure and test execution * wip: dependencies * wip: changed test scenarios wording * wip: k8s apply * improve init of tests * fix bug on state * model embeds world to be able to perform world type operations * changed context and model labels * client with watcher * wip: storage watcher * fix scenario bug * docs * expose k8s client * feat: watcher storage, saves the latest state of crds to later assert on state * feat: watcher with wait for condition interface * docs: added todos and commented feature test
1 parent 21cbc5a commit 52e9a29

23 files changed

+1267
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Seldon Core 2 – Godog Test Architecture
2+
3+
This document describes the architecture of the BDD-style test suites for Seldon Core 2
4+
using [godog](https://github.com/cucumber/godog) and Kubernetes.
5+
6+
The goals of this architecture are:
7+
8+
- Run **the same logical tests** against **different server configurations**.
9+
- Drive tests via **feature tags + config**, not hard-coded setup.
10+
- Provide a clean **domain-focused step API** (e.g. “models”, “pipelines”, …).
11+
- Maintain an **in-memory view of Kubernetes resources** to make assertions easy and fast.
12+
- Have flexibility to add future dependencies such as k6 or chaosmonkey
13+
14+
---
15+
16+
## 1. High-Level Overview
17+
18+
At a high level:
19+
20+
- **`TestMain`** creates and runs a `godog.TestSuite`.
21+
- **`InitializeTestSuite`** creates long-lived test dependencies:
22+
- Kubernetes client(s)
23+
- A Kubernetes watcher for CRDs with `test-suite=godogs`
24+
- Reads/configures server setup from flags/config
25+
- Optionally deploys server replicas and other shared infra
26+
- **`InitializeScenario`** runs per scenario:
27+
- Creates a fresh **World** object (per-scenario state holder)
28+
- Resets CRDs in the cluster (e.g. deletes test models)
29+
- Creates a fresh **Model** for the scenario
30+
- Registers domain-specific steps (e.g. model steps) against this World/Model
31+
- **Feature files** (Gherkin) describe behavior in domain language:
32+
- e.g. “Given I have an "iris" model … Then the model should eventually become Ready”
33+
- **A watcher** keeps an up-to-date in-memory store of CRDs with label `test-suite=godogs` for fast, poll-free
34+
assertions.
35+
36+
## Run a test case
37+
38+
```shell
39+
go test --godog.tags='@0' --godog.concurrency=1 -race
40+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#@AutoscalingModel
2+
#Feature: Model Autoscaling
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
@ModelDeployment @Functional @Models
2+
Feature: Model deployment
3+
In order to make a model available for inference
4+
As a model user
5+
I need to create a Model resource and verify it is deployed
6+
7+
@0
8+
Scenario: Success - Load a model
9+
Given I have an "iris" model
10+
When the model is applied
11+
Then the model should eventually become Ready
12+
13+
14+
@0
15+
Scenario: Success - Load a model again
16+
Given I have an "iris" model
17+
When the model is applied
18+
Then the model should eventually become Ready
19+
20+
# this approach might be more reusable specially for complex test cases, its all how expressive we want to be
21+
Scenario: Load model
22+
Given I have a model:
23+
"""
24+
25+
"""
26+
When the model is applied
27+
Then the model should eventually become Ready
28+
29+
Scenario: Success - Load a model and expect status model available
30+
Given I have an "iris" model
31+
When the model is applied
32+
And the model eventually becomes Ready
33+
Then the model status message should eventually be "ModelAvailable"
34+
35+
Scenario: Success - Load a model with min replicas
36+
Given I have an "iris" model
37+
And the model has "1" min replicas
38+
When the model is applied
39+
Then the model should eventually become Ready
40+
41+
42+
Scenario: Success - Load a big model
43+
Given I have an "large-model" model
44+
When the model is applied
45+
Then the model should eventually become Ready
46+
47+
# this would belong more to the feature of model server scheduling or capabilities
48+
Scenario: Fail Load Model - no server capabilities in cluster
49+
Given Given I have an "iris" model
50+
And the model has "xgboost" capabilities
51+
And there is no server in the cluster with capabilities "xgboost"
52+
When the model is applied
53+
Then the model eventually becomes not Ready
54+
And the model status message should eventually be "ModelFailed"
55+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#@ModelDisruption @Models @Disruption
2+
#Feature: Model resilence to Core 2 disruption
3+
#
4+
# Background:
5+
# Given a clean test namespace
6+
# And a Ready model "resilient-model" with capabilities "mlserver"
7+
#
8+
# Scenario: Model keeps serving during a control plane restart
9+
# Given a load test of 100 RPS is running against model "resilient-model"
10+
# When I restart the Seldon Core 2 control plane
11+
# Then at least 99% of requests should succeed during "2m"
12+
# And the 95th percentile latency during "2m" should be less than "250ms"
13+
# And no outage should last longer than "10s"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#@ModelInference @Models @Inference
2+
#Feature Basic model inferencing
3+
#
4+
# Background:
5+
# Given a clean test namespace
6+
#
7+
# Scenario: Model can serve prediction
8+
# Given I have an "iris" model
9+
# And the model is applied
10+
# And the model eventually becomes Ready
11+
# When I send a prediction request with payload:
12+
# """
13+
# { "inputs": [1.0, 2.0, 3.0] }
14+
# """
15+
# Then the response status should be 200
16+
# And the response body should contain "predictions"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#@ModelLoad @Models @Load
2+
#Feature: Model performance under load
3+
#
4+
## the model replicas could default to the max replicas of the available ml server
5+
# Background:
6+
# Given a clean test namespace
7+
# And a Ready model "load-model" with capabilities "mlserver"
8+
#
9+
# Scenario: Model meets latency SLO at 200 RPS
10+
# When I run a load test of 200 RPS for "2m" against model "load-model"
11+
# Then the 95th percentile latency should be less than "150ms"
12+
# And the error rate should be less than "1%"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#@ModelParametrizedParameters
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#@ModelPartialScheduling
2+
#Feature: Partial Model Scheduling
3+
# In order to make a model partially available for inference
4+
# As a model user
5+
# I need to create a Model resource with min replicas less than the available server replicas and replicas bigger than the available server replicas and verify that the model deploys the minimum amount of possible model replicas and becomes ready
6+
#
7+
# Scenario: Success - Load a model with partial replicas
8+
# Given I have an "iris" model
9+
# And the model has "1" min replicas
10+
# And the model has "5" max replicas
11+
# And the model has "1" replicas
12+
# When the model is applied
13+
# Then the model should eventually becomes Ready
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#@ModelStorageSecrets

tests/integration/godog/features/pipeline/chain.feature

Whitespace-only changes.

0 commit comments

Comments
 (0)