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

Write xgboost_synthetic test output to html #735

Merged
merged 20 commits into from
Feb 15, 2020
1 change: 1 addition & 0 deletions py/kubeflow/examples/create_e2e_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ def _build_tests_dag_notebooks(self):
# Test timeout in seconds.
"--timeout=1800",
"--junitxml=" + self.artifacts_dir + "/junit_xgboost-synthetic-test.xml",
"--notebook_artifacts_dir=" + self.artifacts_dir + "/xgboost-synthetic-test-notebooks",
]

dependencies = []
Expand Down
7 changes: 7 additions & 0 deletions xgboost_synthetic/testing/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ def pytest_addoption(parser):
parser.addoption(
"--repos", help="The repos to checkout; leave blank to use defaults",
type=str, default="")
parser.addoption(
"--notebook_artifacts_dir", help="Directory to store notebook artifacts",
type=str, default="")

@pytest.fixture
def name(request):
Expand All @@ -32,3 +35,7 @@ def image(request):
@pytest.fixture
def repos(request):
return request.config.getoption("--repos")

@pytest.fixture
def notebook_artifacts_dir(request):
return request.config.getoption("--notebook_artifacts_dir")
14 changes: 14 additions & 0 deletions xgboost_synthetic/testing/execute_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import os
import subprocess

from kubeflow.testing import util as kf_util

logger = logging.getLogger(__name__)

def prepare_env():
subprocess.check_call(["pip3", "install", "-U", "papermill"])
subprocess.check_call(["pip3", "install", "-U", "nbconvert"])
subprocess.check_call(["pip3", "install", "-U", "nbformat"])
subprocess.check_call(["pip3", "install", "-r", "../requirements.txt"])


Expand All @@ -22,7 +25,18 @@ def execute_notebook(notebook_path, parameters=None):

def run_notebook_test(notebook_path, expected_messages, parameters=None):
output_path = execute_notebook(notebook_path, parameters=parameters)

import nbformat #pylint: disable=import-error
import nbconvert #pylint: disable=import-error

actual_output = open(output_path, 'r').read()

nb = nbformat.reads(actual_output, as_version=4)
html_exporter = nbconvert.HTMLExporter()
(html_output, _) = html_exporter.from_notebook_node(nb)
gcs_path = os.getenv("OUTPUT_GCS")
kf_util.upload_to_gcs(html_output, gcs_path)

for expected_message in expected_messages:
if not expected_message in actual_output:
logger.error(actual_output)
Expand Down
27 changes: 26 additions & 1 deletion xgboost_synthetic/testing/xgboost_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pytest

from google.cloud import storage
from kubernetes import client as k8s_client
from kubeflow.testing import argo_build_util
from kubeflow.testing import util
Expand All @@ -17,7 +18,7 @@
# and we want signal in postsubmits and periodics
@pytest.mark.xfail(os.getenv("JOB_TYPE") == "presubmit", reason="Flaky")
def test_xgboost_synthetic(record_xml_attribute, name, namespace, # pylint: disable=too-many-branches,too-many-statements
repos, image):
repos, image, notebook_artifacts_dir):
'''Generate Job and summit.'''
util.set_pytest_junit(record_xml_attribute, "test_xgboost_synthetic")

Expand All @@ -35,13 +36,28 @@ def test_xgboost_synthetic(record_xml_attribute, name, namespace, # pylint: disa
if not repos:
repos = argo_build_util.get_repo_from_prow_env()

repos += ",kubeflow/testing@HEAD"
logging.info("Repos set to %s", repos)
job["spec"]["template"]["spec"]["initContainers"][0]["command"] = [
"/usr/local/bin/checkout_repos.sh",
"--repos=" + repos,
"--src_dir=/src",
"--depth=all",
]

nb_bucket = "kubeflow-ci-deployment"
nb_path = os.path.join(
"xgboost_synthetic_testing",
os.getenv("JOB_TYPE"),
os.getenv("HOSTNAME"),
"notebook.html"
)
output_gcs = util.to_gcs_uri(nb_bucket, nb_path)
logging.info("Tested notebook will be outputed to: %s", output_gcs)
job["spec"]["template"]["spec"]["containers"][0]["env"] = [
{"name": "PYTHONPATH", "value": "/src/kubeflow/testing/py"},
{"name": "OUTPUT_GCS", "value": output_gcs},
]
job["spec"]["template"]["spec"]["containers"][0]["image"] = image
util.load_kube_config(persist_config=False)

Expand Down Expand Up @@ -75,6 +91,15 @@ def test_xgboost_synthetic(record_xml_attribute, name, namespace, # pylint: disa

last_condition = final_job.status.conditions[-1]

# Download notebook html to artifacts
notebook_artifacts_path = os.path.join(notebook_artifacts_dir, "notebook.html")
logging.info("Writing notebook artifact to: %s", notebook_artifacts_path)
os.makedirs(notebook_artifacts_dir, exist_ok=True)
storage_client = storage.Client()
bucket = storage_client.get_bucket(nb_bucket)
blob = bucket.get_blob(nb_path)
blob.download_to_filename(notebook_artifacts_path)

if last_condition.type not in ["Complete"]:
logging.error("Job didn't complete successfully")
raise RuntimeError("Job {0}.{1} failed".format(namespace, name))
Expand Down