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

Tests for Extensions #978

Merged
Merged
6 changes: 4 additions & 2 deletions test/core/contexts.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
"BasicUnboundedForeachTest",
"NestedUnboundedForeachTest",
"DetectSegFaultTest",
"TimeoutDecoratorTest"
"TimeoutDecoratorTest",
"CardExtensionsImportTest"
]
},
{
Expand Down Expand Up @@ -126,7 +127,8 @@
"BasicUnboundedForeachTest",
"NestedUnboundedForeachTest",
"DetectSegFaultTest",
"TimeoutDecoratorTest"
"TimeoutDecoratorTest",
"CardExtensionsImportTest"
]
}
],
Expand Down
58 changes: 58 additions & 0 deletions test/core/tests/card_extension_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from metaflow_test import MetaflowTest, ExpectationFailed, steps, tag


class CardExtensionsImportTest(MetaflowTest):
"""
- Requires on tests/extensions/packages to be installed.
"""

PRIORITY = 5

@tag('card(type="card_ext_init_b",save_errors=False)')
@tag('card(type="card_ext_init_a",save_errors=False)')
@tag('card(type="card_ns_subpackage",save_errors=False)')
@tag('card(type="card_init",save_errors=False)')
@steps(0, ["start"])
def step_start(self):
from metaflow import current

self.task = current.pathspec

@steps(1, ["all"])
def step_all(self):
pass

def check_results(self, flow, checker):
run = checker.get_run()
if run is None:
# This means CliCheck is in context.
for step in flow:
if step != "start":
continue
cli_check_dict = checker.artifact_dict(step.name, "task")
for task_pathspec in cli_check_dict:
full_pathspec = "/".join([flow.name, task_pathspec])
task_id = task_pathspec.split("/")[-1]
cards_info = checker.list_cards(step.name, task_id)
# Just check if the cards are created.
assert_equals(
cards_info is not None
and "cards" in cards_info
and len(cards_info["cards"]) == 4,
True,
)
else:
# This means MetadataCheck is in context.
for step in flow:
if step.name != "start":
continue
meta_check_dict = checker.artifact_dict(step.name, "task")
for task_id in meta_check_dict:
full_pathspec = meta_check_dict[task_id]["task"]
cards_info = checker.list_cards(step.name, task_id)
assert_equals(
cards_info is not None
and "cards" in cards_info
and len(cards_info["cards"]) == 4,
True,
)
5 changes: 5 additions & 0 deletions test/extensions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Extensions Testing Framework.

What does this framework do ? It installs the extensions and then runs the test suite which leverages the extensions.

Currently installs the cards related packages.
3 changes: 3 additions & 0 deletions test/extensions/install_packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pip install ./packages/card_via_extinit
pip install ./packages/card_via_init
pip install ./packages/card_via_ns_subpackage
3 changes: 3 additions & 0 deletions test/extensions/packages/card_via_extinit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# card_via_extinit

This test will check if card extensions installed with `mfextinit_*.py` work with Metaflow.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from metaflow.cards import MetaflowCard


class TestMockCard(MetaflowCard):
type = "card_ext_init_a"

def __init__(self, options={"key": "task"}, **kwargs):
self._key = options["key"] if "key" in options else "task"

def render(self, task):
task_data = task[self._key].data
return "%s" % task_data


CARDS = [TestMockCard]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from metaflow.cards import MetaflowCard


class TestMockCard(MetaflowCard):
type = "card_ext_init_b"

def __init__(self, options={"key": "task"}, **kwargs):
self._key = options["key"] if "key" in options else "task"

def render(self, task):
task_data = task[self._key].data
return "%s" % task_data


CARDS = [TestMockCard]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .card_a import CARDS as a
from .card_b import CARDS as b

CARDS = a + b
21 changes: 21 additions & 0 deletions test/extensions/packages/card_via_extinit/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from setuptools import find_namespace_packages, setup


def get_long_description() -> str:
with open("README.md") as fh:
return fh.read()


setup(
name="metaflow-card-via-extinit",
version="1.0.0",
description="A desription of your card",
long_description=get_long_description(),
long_description_content_type="text/markdown",
author="Your Name",
author_email="[email protected]",
license="Apache Software License 2.0",
packages=find_namespace_packages(include=["metaflow_extensions.*"]),
include_package_data=True,
zip_safe=False,
)
3 changes: 3 additions & 0 deletions test/extensions/packages/card_via_init/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# card_via_init

This test checks if card extensions directly with a `plugins/cards` directory structure work as planned.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from metaflow.cards import MetaflowCard


class TestMockCard(MetaflowCard):
type = "card_init"

def __init__(self, options={"key": "task"}, **kwargs):
self._key = options["key"] if "key" in options else "task"

def render(self, task):
task_data = task[self._key].data
return "%s" % task_data


CARDS = [TestMockCard]
21 changes: 21 additions & 0 deletions test/extensions/packages/card_via_init/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from setuptools import find_namespace_packages, setup


def get_long_description() -> str:
with open("README.md") as fh:
return fh.read()


setup(
name="metaflow-card-via-init",
version="1.0.0",
description="A desription of your card",
long_description=get_long_description(),
long_description_content_type="text/markdown",
author="Your Name",
author_email="[email protected]",
license="Apache Software License 2.0",
packages=find_namespace_packages(include=["metaflow_extensions.*"]),
include_package_data=True,
zip_safe=False,
)
3 changes: 3 additions & 0 deletions test/extensions/packages/card_via_ns_subpackage/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# card_ns_subpackage

This test will check if card extensions installed subpackages under namespace packages work
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from metaflow.cards import MetaflowCard


class TestMockCard(MetaflowCard):
type = "card_ns_subpackage"

def __init__(self, options={"key": "task"}, **kwargs):
self._key = options["key"] if "key" in options else "task"

def render(self, task):
task_data = task[self._key].data
return "%s" % task_data


CARDS = [TestMockCard]
21 changes: 21 additions & 0 deletions test/extensions/packages/card_via_ns_subpackage/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from setuptools import find_namespace_packages, setup


def get_long_description() -> str:
with open("README.md") as fh:
return fh.read()


setup(
name="metaflow-card-via-nspackage",
version="1.0.0",
description="A desription of your card",
long_description=get_long_description(),
long_description_content_type="text/markdown",
author="Your Name",
author_email="[email protected]",
license="Apache Software License 2.0",
packages=find_namespace_packages(include=["metaflow_extensions.*"]),
include_package_data=True,
zip_safe=False,
)
8 changes: 7 additions & 1 deletion test_runner
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ install_deps() {
done
}

install_extensions() {
cd test/extensions
sh install_packages.sh
cd ../../
}

run_tests() {
cd test/core && PYTHONPATH=`pwd`/../../ python3 run_tests.py --num-parallel 8
}

install_deps && run_tests
install_deps && install_extensions && run_tests