Skip to content

Commit 27121c5

Browse files
Better test-local and test-integ
1 parent 192cdff commit 27121c5

File tree

6 files changed

+62
-12
lines changed

6 files changed

+62
-12
lines changed

Examples.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ detectors = gl.list_detectors(page=3, page_size=25)
4343
#### Submit an image query
4444

4545
```Python
46-
from groundlight.images import jpeg_from_file # utility function for convenience
47-
48-
image_bytesio = jpeg_from_file("test/assets/dog.jpeg")
49-
image_query = gl.submit_image_query(detector_id="YOUR_DETECTOR_ID", image_bytesio=image_bytesio)
46+
image_query = gl.submit_image_query(detector_id="YOUR_DETECTOR_ID", image="path/to/filename.jpeg")
5047
```
5148

5249
#### Retrieve an image query

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.PHONY: all test clean
2+
13
# Java weirdness - see https://github.com/OpenAPITools/openapi-generator/issues/11763#issuecomment-1098337960
24
generate: ## Generate the SDK from our public openapi spec
35
_JAVA_OPTIONS="--add-opens=java.base/java.lang=ALL-UNNAMED \
@@ -6,3 +8,10 @@ generate: ## Generate the SDK from our public openapi spec
68
-g python \
79
-o ./generated
810
poetry run datamodel-codegen --input spec/public-api.yaml --output generated/model.py
11+
12+
test-local: ## Run integration tests against an API server running at http://localhost:8000/device-api (needs GROUNDLIGHT_API_TOKEN)
13+
GROUNDLIGHT_TEST_API_ENDPOINT="http://localhost:8000/device-api" poetry run pytest --cov=src test --log-cli-level INFO
14+
15+
16+
test-integ: ## Run integration tests against the integ API server (needs GROUNDLIGHT_API_TOKEN)
17+
GROUNDLIGHT_TEST_API_ENDPOINT="https://device.integ.positronix.ai/device-api" poetry run pytest --cov=src test --log-cli-level INFO

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,38 @@ The auto-generated SDK code is in the `generated/` directory. To re-generate the
7373
$ make generate
7474
```
7575

76+
## Testing
77+
78+
Most tests need an API endpoint to run.
79+
80+
### Local API endpoint
81+
82+
1. Set up a local [janzu API endpoint](https://github.com/positronix-ai/zuuul/blob/main/deploy/README.md#development-using-local-microk8s) running (e.g., on an AWS GPU instance).
83+
84+
1. Set up an ssh tunnel to your laptop. That way, you can access the endpoint at http://localhost:8000/device-api (and the web UI at http://localhost:8000/reef):
85+
86+
```Bash
87+
$ ssh instance-name -L 8000:localhost:80
88+
```
89+
90+
1. Run the tests (with an API token)
91+
92+
```Bash
93+
$ export GROUNDLIGHT_API_TOKEN=tok_abc123
94+
$ make test-local
95+
```
96+
97+
(Note: in theory, it's possible to run the janzu API server on your laptop without microk8s - but some API methods don't work because of the dependence on GPUs)
98+
99+
### Integ API endpoint
100+
101+
1. Run the tests (with an API token)
102+
103+
```Bash
104+
$ export GROUNDLIGHT_API_TOKEN=tok_abc123
105+
$ make test-integ
106+
```
107+
76108
## Releases
77109

78110
To publish a new package version to our [internal pypi repository](https://github.com/positronix-ai/packaging/tree/main/aws), you create a release on github.

src/groundlight/client.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import os
22
from io import BytesIO
3+
from typing import Union
34

45
from model import Detector, ImageQuery, PaginatedDetectorList, PaginatedImageQueryList
56
from openapi_client import ApiClient, Configuration
67
from openapi_client.api.detectors_api import DetectorsApi
78
from openapi_client.api.image_queries_api import ImageQueriesApi
89
from openapi_client.model.detector_creation_input import DetectorCreationInput
910

11+
from groundlight.images import bytesio_from_jpeg_file
12+
1013
API_TOKEN_WEB_URL = "https://app.positronix.ai/reef/my-account/api-tokens"
1114
API_TOKEN_VARIABLE_NAME = "GROUNDLIGHT_API_TOKEN"
1215

@@ -75,6 +78,16 @@ def list_image_queries(self, page: int = 1, page_size: int = 10) -> PaginatedIma
7578
obj = self.image_queries_api.list_image_queries(page=page, page_size=page_size)
7679
return PaginatedImageQueryList.parse_obj(obj.to_dict())
7780

78-
def submit_image_query(self, detector_id: str, image_bytesio: BytesIO) -> ImageQuery:
81+
def submit_image_query(self, detector_id: str, image: Union[str, bytes, BytesIO]) -> ImageQuery:
82+
if isinstance(image, str):
83+
# Assume it is a filename
84+
image_bytesio = bytesio_from_jpeg_file(image)
85+
elif isinstance(image, bytes):
86+
# Create a BytesIO object
87+
image_bytesio = BytesIO(image)
88+
elif isinstance(image, BytesIO):
89+
# Already in the right format
90+
image_bytesio = image
91+
7992
obj = self.image_queries_api.submit_image_query(detector_id=detector_id, body=image_bytesio)
8093
return ImageQuery.parse_obj(obj.to_dict())

src/groundlight/images.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from PIL import Image
44

55

6-
def jpeg_from_file(image_filename) -> io.BytesIO:
6+
def bytesio_from_jpeg_file(image_filename) -> io.BytesIO:
77
"""
88
Get a BytesIO object from a JPEG filename.
99
"""

test/integration/test_groundlight.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
import os
12
from datetime import datetime
23

34
import pytest
45
from groundlight import Groundlight
5-
from groundlight.images import jpeg_from_file
66
from model import Detector, ImageQuery, PaginatedDetectorList, PaginatedImageQueryList
77

88

99
@pytest.fixture
1010
def gl() -> Groundlight:
11-
return Groundlight(endpoint="http://localhost:8000/device-api")
11+
endpoint = os.environ.get("GROUNDLIGHT_TEST_API_ENDPOINT", "http://localhost:8000/device-api")
12+
return Groundlight(endpoint=endpoint)
1213

1314

1415
@pytest.fixture
@@ -20,8 +21,7 @@ def detector(gl: Groundlight) -> Detector:
2021

2122
@pytest.fixture
2223
def image_query(gl: Groundlight, detector: Detector) -> ImageQuery:
23-
image_bytesio = jpeg_from_file("test/assets/dog.jpeg")
24-
return gl.submit_image_query(detector_id=detector.id, image_bytesio=image_bytesio)
24+
return gl.submit_image_query(detector_id=detector.id, image="test/assets/dog.jpeg")
2525

2626

2727
@pytest.mark.skip(reason="We don't want to create a million detectors")
@@ -48,8 +48,7 @@ def test_get_detector(gl: Groundlight, detector: Detector):
4848

4949
@pytest.mark.skip(reason="We don't want to create a million detectors and image_queries")
5050
def test_submit_image_query(gl: Groundlight, detector: Detector):
51-
image_bytesio = jpeg_from_file("test/assets/dog.jpeg")
52-
_image_query = gl.submit_image_query(detector_id=detector.id, image_bytesio=image_bytesio)
51+
_image_query = gl.submit_image_query(detector_id=detector.id, image="test/assets/dog.jpeg")
5352
assert str(_image_query)
5453
assert isinstance(_image_query, ImageQuery)
5554

0 commit comments

Comments
 (0)