diff --git a/imperative/python/test/conftest.py b/imperative/python/test/conftest.py new file mode 100644 index 0000000000000000000000000000000000000000..f0de9679e3b283070a745313f13cf634a546eaf9 --- /dev/null +++ b/imperative/python/test/conftest.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.append(os.path.join(os.path.dirname(__file__), "helpers")) diff --git a/imperative/python/test/helpers/utils.py b/imperative/python/test/helpers/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..e62965826b5316ad5608a2d904e7fe338411fe6d --- /dev/null +++ b/imperative/python/test/helpers/utils.py @@ -0,0 +1,66 @@ +import numpy as np + +from megengine import tensor + + +def _default_compare_fn(x, y): + np.testing.assert_allclose(x.numpy(), y, rtol=1e-6) + + +def opr_test(cases, func, compare_fn=_default_compare_fn, ref_fn=None, **kwargs): + """ + :param cases: the list which have dict element, the list length should be 2 for dynamic shape test. + and the dict should have input, + and should have output if ref_fn is None. + should use list for multiple inputs and outputs for each case. + :param func: the function to run opr. + :param compare_fn: the function to compare the result and expected, use assertTensorClose if None. + :param ref_fn: the function to generate expected data, should assign output if None. + + Examples: + + .. code-block:: + + dtype = np.float32 + cases = [{"input": [10, 20]}, {"input": [20, 30]}] + opr_test(cases, + F.eye, + ref_fn=lambda n, m: np.eye(n, m).astype(dtype), + dtype=dtype) + + """ + + def check_results(results, expected): + if not isinstance(results, (tuple, list)): + results = (results,) + for r, e in zip(results, expected): + compare_fn(r, e) + + def get_param(cases, idx): + case = cases[idx] + inp = case.get("input", None) + outp = case.get("output", None) + if inp is None: + raise ValueError("the test case should have input") + if not isinstance(inp, (tuple, list)): + inp = (inp,) + if ref_fn is not None and callable(ref_fn): + outp = ref_fn(*inp) + if outp is None: + raise ValueError("the test case should have output or reference function") + if not isinstance(outp, (tuple, list)): + outp = (outp,) + + return inp, outp + + if len(cases) == 0: + raise ValueError("should give one case at least") + + if not callable(func): + raise ValueError("the input func should be callable") + + inp, outp = get_param(cases, 0) + inp_tensor = [tensor(inpi) for inpi in inp] + + results = func(*inp_tensor, **kwargs) + check_results(results, outp) diff --git a/imperative/python/test/run.sh b/imperative/python/test/run.sh index 967740a87fe4c7ebffaaabdffb2dbd0fdc328879..4920e2e9d08414b7066f874220ff19a799e761f3 100755 --- a/imperative/python/test/run.sh +++ b/imperative/python/test/run.sh @@ -13,9 +13,9 @@ else fi pushd $(dirname "${BASH_SOURCE[0]}")/.. >/dev/null - PYTHONPATH="." PY_IGNORE_IMPORTMISMATCH=1 python3 -m pytest $test_dirs -m 'not isolated_distributed' + PYTHONPATH="." python3 -m pytest $test_dirs -m 'not isolated_distributed' if [[ "$TEST_PLAT" == cuda ]]; then echo "test GPU pytest now" - PYTHONPATH="." PY_IGNORE_IMPORTMISMATCH=1 python3 -m pytest $test_dirs -m 'isolated_distributed' + PYTHONPATH="." python3 -m pytest $test_dirs -m 'isolated_distributed' fi popd >/dev/null diff --git a/imperative/python/test/unit/data/__init__.py b/imperative/python/test/unit/data/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/imperative/python/test/unit/functional/__init__.py b/imperative/python/test/unit/functional/__init__.py deleted file mode 100644 index 1207b5d98cd3578bc39e9ce600a1254a434880c8..0000000000000000000000000000000000000000 --- a/imperative/python/test/unit/functional/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -# MegEngine is Licensed under the Apache License, Version 2.0 (the "License") -# -# Copyright (c) 2014-2020 Megvii Inc. All rights reserved. -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/imperative/python/test/unit/functional/test_functional.py b/imperative/python/test/unit/functional/test_functional.py index 0778fb153de7c5226866eeb569c150759d33a880..e8608954de00f550907191c008d5f40972f2a536 100644 --- a/imperative/python/test/unit/functional/test_functional.py +++ b/imperative/python/test/unit/functional/test_functional.py @@ -10,6 +10,7 @@ import itertools import numpy as np import pytest +from utils import opr_test import megengine.core.ops.builtin as builtin import megengine.core.tensor.dtype as dtype @@ -21,68 +22,6 @@ from megengine.core.tensor.utils import make_shape_tuple from megengine.test import assertTensorClose -def _default_compare_fn(x, y): - assertTensorClose(x.numpy(), y) - - -def opr_test(cases, func, compare_fn=_default_compare_fn, ref_fn=None, **kwargs): - """ - func: the function to run opr. - compare_fn: the function to compare the result and expected, use assertTensorClose if None. - ref_fn: the function to generate expected data, should assign output if None. - cases: the list which have dict element, the list length should be 2 for dynamic shape test. - and the dict should have input, - and should have output if ref_fn is None. - should use list for multiple inputs and outputs for each case. - kwargs: The additional kwargs for opr func. - - simple examples: - - dtype = np.float32 - cases = [{"input": [10, 20]}, {"input": [20, 30]}] - opr_test(cases, - F.eye, - ref_fn=lambda n, m: np.eye(n, m).astype(dtype), - dtype=dtype) - - """ - - def check_results(results, expected): - if not isinstance(results, (tuple, list)): - results = (results,) - for r, e in zip(results, expected): - compare_fn(r, e) - - def get_param(cases, idx): - case = cases[idx] - inp = case.get("input", None) - outp = case.get("output", None) - if inp is None: - raise ValueError("the test case should have input") - if not isinstance(inp, (tuple, list)): - inp = (inp,) - if ref_fn is not None and callable(ref_fn): - outp = ref_fn(*inp) - if outp is None: - raise ValueError("the test case should have output or reference function") - if not isinstance(outp, (tuple, list)): - outp = (outp,) - - return inp, outp - - if len(cases) == 0: - raise ValueError("should give one case at least") - - if not callable(func): - raise ValueError("the input func should be callable") - - inp, outp = get_param(cases, 0) - inp_tensor = [tensor(inpi) for inpi in inp] - - results = func(*inp_tensor, **kwargs) - check_results(results, outp) - - def test_where(): maskv0 = np.array([[1, 0], [0, 1]], dtype=np.bool_) xv0 = np.array([[1, np.inf], [np.nan, 4]], dtype=np.float32) diff --git a/imperative/python/test/unit/functional/test_distributed.py b/imperative/python/test/unit/functional/test_functional_distributed.py similarity index 100% rename from imperative/python/test/unit/functional/test_distributed.py rename to imperative/python/test/unit/functional/test_functional_distributed.py diff --git a/imperative/python/test/unit/functional/test_math.py b/imperative/python/test/unit/functional/test_math.py index 64e0b10fde1b95472dfeaf84acbf47dcd52ea886..e0c28a3b5111844ea5da129df6f91a7beddf62b2 100644 --- a/imperative/python/test/unit/functional/test_math.py +++ b/imperative/python/test/unit/functional/test_math.py @@ -9,78 +9,13 @@ from functools import partial import numpy as np +from utils import opr_test import megengine.functional as F from megengine import tensor from megengine.test import assertTensorClose -def _default_compare_fn(x, y): - assertTensorClose(x.numpy(), y) - - -def opr_test(cases, func, compare_fn=_default_compare_fn, ref_fn=None, **kwargs): - """ - func: the function to run opr. - compare_fn: the function to compare the result and expected, use assertTensorClose if None. - ref_fn: the function to generate expected data, should assign output if None. - cases: the list which have dict element, the list length should be 2 for dynamic shape test. - and the dict should have input, - and should have output if ref_fn is None. - should use list for multiple inputs and outputs for each case. - kwargs: The additional kwargs for opr func. - - simple examples: - - dtype = np.float32 - cases = [{"input": [10, 20]}, {"input": [20, 30]}] - opr_test(cases, - F.eye, - ref_fn=lambda n, m: np.eye(n, m).astype(dtype), - dtype=dtype) - - """ - - def check_results(results, expected): - if not isinstance(results, tuple): - results = (results,) - for r, e in zip(results, expected): - compare_fn(r, e) - - def get_param(cases, idx): - case = cases[idx] - inp = case.get("input", None) - outp = case.get("output", None) - if inp is None: - raise ValueError("the test case should have input") - if not isinstance(inp, list): - inp = (inp,) - else: - inp = tuple(inp) - if ref_fn is not None and callable(ref_fn): - outp = ref_fn(*inp) - if outp is None: - raise ValueError("the test case should have output or reference function") - if not isinstance(outp, list): - outp = (outp,) - else: - outp = tuple(outp) - - return inp, outp - - if len(cases) == 0: - raise ValueError("should give one case at least") - - if not callable(func): - raise ValueError("the input func should be callable") - - inp, outp = get_param(cases, 0) - inp_tensor = [tensor(inpi) for inpi in inp] - - results = func(*inp_tensor, **kwargs) - check_results(results, outp) - - def common_test_reduce(opr, ref_opr): data1_shape = (5, 6, 7) data2_shape = (2, 9, 12) diff --git a/imperative/python/test/unit/functional/test_tensor.py b/imperative/python/test/unit/functional/test_tensor.py index c17cf310fe45f4a29f10a8b5f833721b3a929b6c..38193ff31f6f241c989eee8f787c47aec4a4e6f7 100644 --- a/imperative/python/test/unit/functional/test_tensor.py +++ b/imperative/python/test/unit/functional/test_tensor.py @@ -6,10 +6,12 @@ # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +import os import platform import numpy as np import pytest +from utils import opr_test import megengine.functional as F from megengine import tensor @@ -19,72 +21,6 @@ from megengine.distributed.helper import get_device_count_by_fork from megengine.test import assertTensorClose -def _default_compare_fn(x, y): - assertTensorClose(x.numpy(), y) - - -def opr_test(cases, func, compare_fn=_default_compare_fn, ref_fn=None, **kwargs): - """ - func: the function to run opr. - compare_fn: the function to compare the result and expected, use assertTensorClose if None. - ref_fn: the function to generate expected data, should assign output if None. - cases: the list which have dict element, the list length should be 2 for dynamic shape test. - and the dict should have input, - and should have output if ref_fn is None. - should use list for multiple inputs and outputs for each case. - kwargs: The additional kwargs for opr func. - - simple examples: - - dtype = np.float32 - cases = [{"input": [10, 20]}, {"input": [20, 30]}] - opr_test(cases, - F.eye, - ref_fn=lambda n, m: np.eye(n, m).astype(dtype), - dtype=dtype) - - """ - - def check_results(results, expected): - if not isinstance(results, tuple): - results = (results,) - for r, e in zip(results, expected): - compare_fn(r, e) - - def get_param(cases, idx): - case = cases[idx] - inp = case.get("input", None) - outp = case.get("output", None) - if inp is None: - raise ValueError("the test case should have input") - if not isinstance(inp, list): - inp = (inp,) - else: - inp = tuple(inp) - if ref_fn is not None and callable(ref_fn): - outp = ref_fn(*inp) - if outp is None: - raise ValueError("the test case should have output or reference function") - if not isinstance(outp, list): - outp = (outp,) - else: - outp = tuple(outp) - - return inp, outp - - if len(cases) == 0: - raise ValueError("should give one case at least") - - if not callable(func): - raise ValueError("the input func should be callable") - - inp, outp = get_param(cases, 0) - inp_tensor = [tensor(inpi) for inpi in inp] - - results = func(*inp_tensor, **kwargs) - check_results(results, outp) - - def test_eye(): dtype = np.float32 cases = [{"input": [10, 20]}, {"input": [20, 30]}] @@ -265,37 +201,37 @@ def test_flatten(): data1 = np.random.random(data1_shape).astype(np.float32) def compare_fn(x, y): - assert x.numpy().shape == y[0] + assert x.shape[0] == y output0 = (2 * 3 * 4 * 5,) output1 = (4 * 5 * 6 * 7,) cases = [ - {"input": data0, "output": (output0,)}, - {"input": data1, "output": (output1,)}, + {"input": data0, "output": output0}, + {"input": data1, "output": output1}, ] opr_test(cases, F.flatten, compare_fn=compare_fn) output0 = (2, 3 * 4 * 5) output1 = (4, 5 * 6 * 7) cases = [ - {"input": data0, "output": (output0,)}, - {"input": data1, "output": (output1,)}, + {"input": data0, "output": output0}, + {"input": data1, "output": output1}, ] opr_test(cases, F.flatten, compare_fn=compare_fn, start_axis=1) output0 = (2, 3, 4 * 5) output1 = (4, 5, 6 * 7) cases = [ - {"input": data0, "output": (output0,)}, - {"input": data1, "output": (output1,)}, + {"input": data0, "output": output0}, + {"input": data1, "output": output1}, ] opr_test(cases, F.flatten, compare_fn=compare_fn, start_axis=2) output0 = (2, 3 * 4, 5) output1 = (4, 5 * 6, 7) cases = [ - {"input": data0, "output": (output0,)}, - {"input": data1, "output": (output1,)}, + {"input": data0, "output": output0}, + {"input": data1, "output": output1}, ] opr_test(cases, F.flatten, compare_fn=compare_fn, start_axis=1, end_axis=2) @@ -310,7 +246,7 @@ def test_broadcast(): data2 = np.random.random(input2_shape).astype(np.float32) def compare_fn(x, y): - assert x.numpy().shape == y + assert x.shape[0] == y cases = [ {"input": [data1, output1_shape], "output": output1_shape}, diff --git a/imperative/python/test/unit/module/test_tensor.py b/imperative/python/test/unit/module/test_module_tensor.py similarity index 100% rename from imperative/python/test/unit/module/test_tensor.py rename to imperative/python/test/unit/module/test_module_tensor.py