Skip to content
This repository was archived by the owner on Nov 16, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
8162567
Execute the first two sets of unit tests in parallel.
Oct 15, 2019
1ac5033
Wrap test estimator checks in a python unit test.
Oct 15, 2019
04ea00f
Combine the non-extended test runs together to make them more paralle…
Oct 15, 2019
f25bb32
Reverse the tests path args order to try and have test_estimator_chec…
Oct 15, 2019
eeb4e30
Group the unit tests by filename to make their execution more stable.
Oct 15, 2019
a591122
Add the build script changes to build.sh
Oct 15, 2019
7e2a160
Set the minimum number of concurrent unit tests to 4 for the windows …
Oct 15, 2019
c741c9a
Merge branch 'master' into parallel-unit-tests
Oct 15, 2019
e9557ad
Split test_estimator_checks into two separate tests.
Oct 15, 2019
9e6968c
Hard code num concurrent unit tests to 4 for linux and mac. Disable f…
Oct 15, 2019
69dca80
Merge branch 'master' into parallel-unit-tests
Oct 15, 2019
265e04f
Run the two extended tests in parallel.
Oct 16, 2019
5df9ad3
Support running test_estimator_checks as the main file.
Oct 16, 2019
3f8168c
Merge branch 'master' into parallel-unit-tests
Oct 16, 2019
010856d
Merge branch 'master' into parallel-unit-tests
Oct 17, 2019
51cc916
Dynamically generate the test_estimator_checks unit tests.
Oct 17, 2019
9e4efff
Test intentional failure on build servers.
Oct 17, 2019
4afbf71
Merge branch 'master' into parallel-unit-tests
Oct 21, 2019
c33fcc8
Create the test_docs_example unit tests dynamically so they can be pa…
Oct 21, 2019
0e785bc
Update the number of concurrent extended tests.
Oct 21, 2019
1c7de9d
Merge branch 'master' into parallel-unit-tests
Oct 22, 2019
cd81f83
Remove intentional error from test_csr_matrix_output.
Oct 22, 2019
643b39f
Test intentional error in test_estimator_checks.
Oct 22, 2019
dbec373
Remove the intentional error which was used for testing.
Oct 22, 2019
fda4887
Add whitespace change to restart CI run.
Oct 22, 2019
9138a0d
Add whitespace change to start a new CI run.
Oct 22, 2019
95de280
Load balance by sending test grouped by file to any available environ…
Oct 23, 2019
0495136
Add whitespace change to start a new CI run.
Oct 23, 2019
2f6aeb6
Fix KMeansPlusPlus does not work with a cluster size of 1 when using …
Oct 24, 2019
472ad3f
Fix OLS divide by 0 when given a particular set of inputs to fit. Thi…
Oct 24, 2019
b1ccc3a
Fix issue when ranking where the output of TextToKeyConverter was
Oct 24, 2019
be8835f
Remove a test_estimator_check for OrdinaryLeastSquaresRegressor
Oct 24, 2019
3de74fe
Update test_permutation_feature_importance tests to support parallel …
Oct 24, 2019
75df293
Remove --dist=loadfile from the windows unit test run.
Oct 24, 2019
7122e19
Update test_load_save to support parallel execution.
Oct 24, 2019
dbf6c47
Test turning off pytest assert rewriting.
Oct 24, 2019
366b1b0
Test turning off forcing at least 4 concurrent unit tests
Oct 24, 2019
c345a0f
Whitespace change to start a new CI run.
Oct 24, 2019
e6804ea
Test tests run without coverage.
Oct 24, 2019
4cf17cd
Try and capture the test order during the CI run.
Oct 25, 2019
3988ac4
Remove the pydist replay request.
Oct 25, 2019
ed10974
Rerun unit tests one extra time if any failed to check for intermitte…
Oct 25, 2019
8161d24
Turn back on assert rewriting and coverage reporting. Run extended te…
Oct 28, 2019
9822643
Merge branch 'master' into parallel-unit-tests
Oct 28, 2019
c3c4dbd
Remove whitespace at the end of the comment in build.cmd.
Oct 28, 2019
c7bb353
Test errors in tests show up correctly in CI build output.
Oct 28, 2019
8aeab82
Revert the intentional test failures from the previous commit.
Oct 28, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions build.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ if "%InstallPythonPackages%" == "True" (
echo "Installing python packages ... "
echo "#################################"
call "%PythonExe%" -m pip install --upgrade pip
call "%PythonExe%" -m pip install --upgrade nose pytest graphviz imageio pytest-cov "jupyter_client>=4.4.0" "nbconvert>=4.2.0"
call "%PythonExe%" -m pip install --upgrade nose pytest pytest-xdist graphviz imageio pytest-cov "jupyter_client>=4.4.0" "nbconvert>=4.2.0"

if %PythonVersion% == 2.7 (
call "%PythonExe%" -m pip install --upgrade pyzmq
Expand All @@ -414,11 +414,10 @@ set TestsPath1=%PackagePath%\tests
set TestsPath2=%__currentScriptDir%src\python\tests
set TestsPath3=%__currentScriptDir%src\python\tests_extended
set ReportPath=%__currentScriptDir%build\TestCoverageReport
call "%PythonExe%" -m pytest --verbose --maxfail=1000 --capture=sys "%TestsPath1%" --cov="%PackagePath%" --cov-report term-missing --cov-report html:"%ReportPath%"
if errorlevel 1 (
goto :Exit_Error
)
call "%PythonExe%" -m pytest --verbose --maxfail=1000 --capture=sys "%TestsPath2%" --cov="%PackagePath%" --cov-report term-missing --cov-report html:"%ReportPath%"
set NumConcurrentTests=%NUMBER_OF_PROCESSORS%
if %NumConcurrentTests% LSS 4 set NumConcurrentTests=4

call "%PythonExe%" -m pytest -n %NumConcurrentTests% --verbose --maxfail=1000 --capture=sys "%TestsPath2%" "%TestsPath1%" --cov="%PackagePath%" --cov-report term-missing --cov-report html:"%ReportPath%"
if errorlevel 1 (
goto :Exit_Error
)
Expand Down
5 changes: 2 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ then
exit 1
fi
# Review: Adding "--upgrade" to pip install will cause problems when using Anaconda as the python distro because of Anaconda's quirks with pytest.
"${PythonExe}" -m pip install nose "pytest>=4.4.0" graphviz "pytest-cov>=2.6.1" "jupyter_client>=4.4.0" "nbconvert>=4.2.0"
"${PythonExe}" -m pip install nose "pytest>=4.4.0" pytest-xdist graphviz "pytest-cov>=2.6.1" "jupyter_client>=4.4.0" "nbconvert>=4.2.0"
if [ ${PythonVersion} = 2.7 ]
then
"${PythonExe}" -m pip install --upgrade pyzmq
Expand All @@ -307,8 +307,7 @@ then
TestsPath2=${__currentScriptDir}/src/python/tests
TestsPath3=${__currentScriptDir}/src/python/tests_extended
ReportPath=${__currentScriptDir}/build/TestCoverageReport
"${PythonExe}" -m pytest --verbose --maxfail=1000 --capture=sys "${TestsPath1}"
"${PythonExe}" -m pytest --verbose --maxfail=1000 --capture=sys "${TestsPath2}"
"${PythonExe}" -m pytest -n 4 --verbose --maxfail=1000 --capture=sys "${TestsPath2}" "${TestsPath1}"

if [ ${__runExtendedTests} = true ]
then
Expand Down
197 changes: 107 additions & 90 deletions src/python/tests/test_estimator_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""
import json
import os
import unittest

from nimbusml.decomposition import FactorizationMachineBinaryClassifier
from nimbusml.ensemble import EnsembleClassifier
Expand Down Expand Up @@ -247,6 +248,14 @@

MULTI_OUTPUT.extend(MULTI_OUTPUT_EX)

skip_epoints = set([
'OneVsRestClassifier',
'TreeFeaturizer',
# skip SymSgdBinaryClassifier for now, because of crashes.
'SymSgdBinaryClassifier',
'DatasetTransformer'
])


def my_import(name):
components = name.split('.')
Expand All @@ -263,97 +272,105 @@ def load_json(file_path):
content_without_comments = '\n'.join(lines)
return json.loads(content_without_comments)

def get_epoints():
epoints = []
my_path = os.path.realpath(__file__)
my_dir = os.path.dirname(my_path)
manifest_diff_json = os.path.join(my_dir, '..', 'tools',
'manifest_diff.json')
manifest_diff = load_json(manifest_diff_json)
for e in manifest_diff['EntryPoints']:
if e['NewName'] not in skip_epoints:
epoints.append((e['Module'], e['NewName']))

skip_epoints = set([
'OneVsRestClassifier',
'TreeFeaturizer',
# skip SymSgdBinaryClassifier for now, because of crashes.
'SymSgdBinaryClassifier',
'DatasetTransformer'
])
return epoints

epoints = []
my_path = os.path.realpath(__file__)
my_dir = os.path.dirname(my_path)
manifest_diff_json = os.path.join(my_dir, '..', 'tools',
'manifest_diff.json')
manifest_diff = load_json(manifest_diff_json)
for e in manifest_diff['EntryPoints']:
if e['NewName'] not in skip_epoints:
epoints.append((e['Module'], e['NewName']))

all_checks = {}
all_failed_checks = {}
all_passed_checks = {}
total_checks_passed = 0

print("total entrypoints: {}", len(epoints))

for e in epoints:
checks = set()
failed_checks = set()
passed_checks = set()
class_name = e[1]
print("======== now Estimator is %s =========== " % class_name)
# skip LighGbm for now, because of random crashes.
if 'LightGbm' in class_name:
continue

mod = __import__('nimbusml.' + e[0], fromlist=[str(class_name)])
the_class = getattr(mod, class_name)
if class_name in INSTANCES:
estimator = INSTANCES[class_name]
else:
estimator = the_class()

if estimator._use_single_input_as_string():
estimator = estimator << 'F0'

for check in _yield_all_checks(class_name, estimator):
# Skip check_dict_unchanged for estimators which
# update the classes_ attribute. For more details
# see https://github.com/microsoft/NimbusML/pull/200
if (check.__name__ == 'check_dict_unchanged') and \
(hasattr(estimator, 'predict_proba') or
hasattr(estimator, 'decision_function')):
continue
def check_entry_points(epoints):
all_checks = {}
all_failed_checks = {}
all_passed_checks = {}
total_checks_passed = 0

if check.__name__ in OMITTED_CHECKS_ALWAYS:
continue
if 'Binary' in class_name and check.__name__ in NOBINARY_CHECKS:
continue
if class_name in OMITTED_CHECKS and check.__name__ in \
OMITTED_CHECKS[class_name]:
continue
if class_name in OMITTED_CHECKS_TUPLE[0] and check.__name__ in \
OMITTED_CHECKS_TUPLE[1]:
print("total entrypoints: {}", len(epoints))

for e in epoints:
checks = set()
failed_checks = set()
passed_checks = set()
class_name = e[1]
print("======== now Estimator is %s =========== " % class_name)
# skip LighGbm for now, because of random crashes.
if 'LightGbm' in class_name:
continue
checks.add(check.__name__)
try:
check(class_name, estimator.clone())
passed_checks.add(check.__name__)
total_checks_passed = total_checks_passed + 1
except Exception as e:
failed_checks.add(check.__name__)

if frozenset(checks) not in all_checks:
all_checks[frozenset(checks)] = []
all_checks[frozenset(checks)].append(class_name)

if len(failed_checks) > 0:
if frozenset(failed_checks) not in all_failed_checks:
all_failed_checks[frozenset(failed_checks)] = []
all_failed_checks[frozenset(failed_checks)].append(class_name)

if frozenset(passed_checks) not in all_passed_checks:
all_passed_checks[frozenset(passed_checks)] = []
all_passed_checks[frozenset(passed_checks)].append(class_name)

if len(all_failed_checks) > 0:
print("Following tests failed for components:")
for key, value in all_failed_checks.items():
print('========================')
print(key)
print(value)
raise RuntimeError("estimator checks failed")
print("success, total checks passed %s ", total_checks_passed)

mod = __import__('nimbusml.' + e[0], fromlist=[str(class_name)])
the_class = getattr(mod, class_name)
if class_name in INSTANCES:
estimator = INSTANCES[class_name]
else:
estimator = the_class()

if estimator._use_single_input_as_string():
estimator = estimator << 'F0'

for check in _yield_all_checks(class_name, estimator):
# Skip check_dict_unchanged for estimators which
# update the classes_ attribute. For more details
# see https://github.com/microsoft/NimbusML/pull/200
if (check.__name__ == 'check_dict_unchanged') and \
(hasattr(estimator, 'predict_proba') or
hasattr(estimator, 'decision_function')):
continue

if check.__name__ in OMITTED_CHECKS_ALWAYS:
continue
if 'Binary' in class_name and check.__name__ in NOBINARY_CHECKS:
continue
if class_name in OMITTED_CHECKS and check.__name__ in \
OMITTED_CHECKS[class_name]:
continue
if class_name in OMITTED_CHECKS_TUPLE[0] and check.__name__ in \
OMITTED_CHECKS_TUPLE[1]:
continue
checks.add(check.__name__)
try:
check(class_name, estimator.clone())
passed_checks.add(check.__name__)
total_checks_passed = total_checks_passed + 1
except Exception as e:
failed_checks.add(check.__name__)

if frozenset(checks) not in all_checks:
all_checks[frozenset(checks)] = []
all_checks[frozenset(checks)].append(class_name)

if len(failed_checks) > 0:
if frozenset(failed_checks) not in all_failed_checks:
all_failed_checks[frozenset(failed_checks)] = []
all_failed_checks[frozenset(failed_checks)].append(class_name)

if frozenset(passed_checks) not in all_passed_checks:
all_passed_checks[frozenset(passed_checks)] = []
all_passed_checks[frozenset(passed_checks)].append(class_name)

if len(all_failed_checks) > 0:
print("Following tests failed for components:")
for key, value in all_failed_checks.items():
print('========================')
print(key)
print(value)
raise RuntimeError("estimator checks failed")
print("success, total checks passed %s ", total_checks_passed)


class TestEstimatorChecks(unittest.TestCase):

def test_estimator_checks_1(self):
epoints = get_epoints()
check_entry_points(epoints[:len(epoints)//2])

def test_estimator_checks_2(self):
epoints = get_epoints()
check_entry_points(epoints[len(epoints)//2:])