Skip to content

Commit

Permalink
Explicit tests for service method registering and inheritance (#556)
Browse files Browse the repository at this point in the history
Per comments in #510 

- [x] Convert test classes to `MockService`
- [x] Add json schema support
  • Loading branch information
bpkroth authored Oct 26, 2023
1 parent 1f0f8ee commit 4784c9f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/microsoft/MLOS/main/mlos_bench/mlos_bench/config/schemas/services/mock-service-subschema.json",
"title": "mlos_bench Mock Service config",
"description": "config for an mlos_bench Mock Service",
"type": "object",
"properties": {
"class": {
"enum": [
"mlos_bench.tests.services.mock_service.MockServiceBase",
"mlos_bench.tests.services.mock_service.MockServiceChild"
]
},
"config": {
"type": "object",
"$comment": "simple class for testing - no config properties accepted atm",
"unevaluatedProperties": false
}
},
"required": ["class"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
{
"$ref": "./local/temp-dir-context-service-subschema.json"
},
{
"$ref": "./mock-service-subschema.json"
},
{
"$ref": "./local/mock/mock-local-exec-service-subschema.json"
},
Expand Down
61 changes: 61 additions & 0 deletions mlos_bench/mlos_bench/tests/services/mock_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
"""
Basic MockService for testing.
See Also: test_service_method_registering.py
"""

from typing import Callable, Dict, List, Optional, Protocol, Union, runtime_checkable

from mlos_bench.services.base_service import Service


@runtime_checkable
class SupportsSomeMethod(Protocol):
"""Protocol for some_method"""

def some_method(self) -> str:
"""some_method"""

def some_other_method(self) -> str:
"""some_other_method"""


class MockServiceBase(Service, SupportsSomeMethod):
"""A base service class for testing."""

def __init__(
self,
config: Optional[dict] = None,
global_config: Optional[dict] = None,
parent: Optional[Service] = None,
methods: Optional[Union[Dict[str, Callable], List[Callable]]] = None) -> None:
super().__init__(
config,
global_config,
parent,
self.merge_methods(methods, [
self.some_method,
self.some_other_method,
]))

def some_method(self) -> str:
"""some_method"""
return f"{self}: base.some_method"

def some_other_method(self) -> str:
"""some_other_method"""
return f"{self}: base.some_other_method"


class MockServiceChild(MockServiceBase, SupportsSomeMethod):
"""A child service class for testing."""

# Intentionally includes no constructor.

def some_method(self) -> str:
"""some_method"""
return f"{self}: child.some_method"
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
"""
Unit tests for Service method registering.
"""

from mlos_bench.services.base_service import Service

from mlos_bench.tests.services.mock_service import SupportsSomeMethod, MockServiceBase, MockServiceChild


def test_service_method_register_without_constructor() -> None:
"""
Test registering a method without a constructor.
"""
some_base_service = MockServiceBase()
some_child_service = MockServiceChild()

# create a mixin service that registers the base service methods
mixin_service = Service()
mixin_service.register(some_base_service.export())

# pylint complains if we try to just assert this directly
# somehow having it in a different scope makes a difference
if isinstance(mixin_service, SupportsSomeMethod):
assert mixin_service.some_method() == f"{some_base_service}: base.some_method"
assert mixin_service.some_other_method() == f"{some_base_service}: base.some_other_method"

# register the child service
mixin_service.register(some_child_service.export())
# check that the inheritance works as expected
assert mixin_service.some_method() == f"{some_child_service}: child.some_method"
assert mixin_service.some_other_method() == f"{some_child_service}: base.some_other_method"
else:
assert False

0 comments on commit 4784c9f

Please sign in to comment.