1. 新增集成测试.2.去除nrtans_py的一些log
This commit is contained in:
parent
831ff52b6f
commit
c07bf4a57a
|
@ -141,7 +141,7 @@ class Netrans():
|
|||
scale = self._format_preprocess_param(kwargs['scale'], grey)
|
||||
data = self._upload_config_scale(data, scale)
|
||||
if 'reverse_channel' in kwargs:
|
||||
data = self._upload_config_reverse_channel(data, kwargs['reverse_channel'],grey)
|
||||
data = self._upload_config_reverse_channel(data, kwargs['reverse_channel'])
|
||||
return data
|
||||
|
||||
|
||||
|
@ -237,6 +237,7 @@ class Netrans():
|
|||
"""
|
||||
func = Config(self)
|
||||
func.inputmeta_gen()
|
||||
|
||||
|
||||
def quantize(self, quantize_type,**kargs):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
import json
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from netrans import Netrans
|
||||
|
||||
|
||||
# ------------ 真实路径 fixture ------------
|
||||
@pytest.fixture(scope="session")
|
||||
def real_model_dir(tmp_path_factory):
|
||||
"""把 tests/data/yolov4_tiny 复制到临时目录"""
|
||||
here = Path(__file__).resolve()
|
||||
src = here.parent.parent.parent / "examples"/ "darknet" / "yolov4_tiny"
|
||||
|
||||
dst = tmp_path_factory.mktemp("real_model")
|
||||
shutil.copytree(src, dst / "yolov4_tiny")
|
||||
return dst / "yolov4_tiny"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def real_netrans():
|
||||
"""返回真实 netrans 可执行文件路径;CI 可注入环境变量"""
|
||||
path = Path(__file__).resolve().parent.parent.parent / "bin"
|
||||
if not path.exists():
|
||||
pytest.skip("真实 netrans 可执行文件不存在")
|
||||
return str(path)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def netrans_real(real_model_dir, real_netrans):
|
||||
"""返回基于真实模型&真实 netrans 的 Netrans 实例"""
|
||||
return Netrans(str(real_model_dir), netrans=real_netrans)
|
||||
|
||||
|
||||
# ------------ 集成测试 ------------
|
||||
@pytest.mark.slow
|
||||
def test_full_integration(netrans_real):
|
||||
"""端到端:load → config → quantize → export"""
|
||||
model_path = Path(netrans_real.model_path)
|
||||
model_name = netrans_real.model_name
|
||||
|
||||
# 1. load
|
||||
netrans_real.load()
|
||||
assert (model_path / f"{model_name}.json").exists()
|
||||
assert (model_path / f"{model_name}.data").exists()
|
||||
|
||||
# 2. config
|
||||
netrans_real.config()
|
||||
inputmeta_file = model_path / f"{model_name}_inputmeta.yml"
|
||||
assert inputmeta_file.exists()
|
||||
|
||||
# 3. quantize
|
||||
netrans_real.quantize("uint8")
|
||||
quant_file = model_path / f"{model_name}_asymmetric_affine.quantize"
|
||||
assert quant_file.exists()
|
||||
|
||||
# 4. export
|
||||
netrans_real.export(quantize_type="uint8")
|
||||
nb_file = model_path / "wksp" / "asymmetric_affine" / "network_binary.nb"
|
||||
assert nb_file.exists()
|
|
@ -0,0 +1,46 @@
|
|||
"""
|
||||
pytest 单文件测试:每个框架一个独立函数
|
||||
运行:
|
||||
pytest test_model_conversion.py -v
|
||||
pytest test_model_conversion.py::test_caffe_conversion
|
||||
"""
|
||||
import os
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from netrans import Netrans
|
||||
|
||||
ROOT = Path(__file__).parent.parent.parent
|
||||
|
||||
# 通用转换函数
|
||||
def _convert(model_dir: Path, mean: float, scale: float):
|
||||
model = Netrans(model_path=str(model_dir))
|
||||
model.model2nbg(
|
||||
quantize_type="uint8",
|
||||
mean=mean,
|
||||
scale=scale,
|
||||
profile=False,
|
||||
)
|
||||
|
||||
# ---------- 各框架独立测试函数 ----------
|
||||
def test_caffe_conversion():
|
||||
model_dir = ROOT / "examples" / "caffe" / "lenet_caffe"
|
||||
_convert(model_dir, mean=0, scale=1.0)
|
||||
|
||||
def test_darknet_conversion():
|
||||
model_dir = ROOT / "examples" / "darknet" / "yolov4_tiny"
|
||||
_convert(model_dir, mean=0, scale=1.0)
|
||||
|
||||
def test_onnx_conversion():
|
||||
model_dir = ROOT / "examples" / "onnx" / "yolov5s"
|
||||
_convert(model_dir, mean=0, scale=0.003921568627)
|
||||
|
||||
def test_tensorflow_conversion():
|
||||
model_dir = ROOT / "examples" / "tensorflow" / "lenet"
|
||||
_convert(model_dir, mean=0, scale=1.0)
|
||||
|
||||
def test_pytorch_conversion():
|
||||
model_dir = ROOT / "examples" / "pytorch" / "resnet50"
|
||||
export_script = model_dir / "export_resnet50_2_onnx.py"
|
||||
assert export_script.exists(), f"{export_script} not found"
|
||||
os.system(f"cd {model_dir} && python export_resnet50_2_onnx.py")
|
||||
_convert(model_dir, mean=0, scale=1.0)
|
|
@ -0,0 +1,209 @@
|
|||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch
|
||||
from netrans import Netrans
|
||||
import shutil
|
||||
@pytest.fixture
|
||||
def mock_model_dir(tmp_path):
|
||||
"""创建复制真实示例目录内容的虚拟模型目录"""
|
||||
# 获取示例目录的绝对路径
|
||||
current_file = Path(__file__)
|
||||
examples_dir = current_file.parent.parent.parent / "examples" # 调整路径层级
|
||||
source_dir = examples_dir / "darknet/yolov4_tiny"
|
||||
|
||||
# 验证源目录存在
|
||||
if not source_dir.exists():
|
||||
raise FileNotFoundError(f"示例目录未找到: {source_dir}")
|
||||
|
||||
# 创建目标目录路径
|
||||
model_dir = tmp_path / "yolov4_tiny"
|
||||
|
||||
# 执行目录复制
|
||||
shutil.copytree(
|
||||
src=str(source_dir),
|
||||
dst=str(model_dir),
|
||||
symlinks=True,
|
||||
ignore_dangling_symlinks=True
|
||||
)
|
||||
|
||||
return model_dir
|
||||
|
||||
@pytest.fixture
|
||||
def mock_netrans_path(tmp_path):
|
||||
"""创建复制真实示例目录内容的虚拟模型目录"""
|
||||
# 获取示例目录的绝对路径
|
||||
current_file = Path(__file__)
|
||||
source_dir = current_file.parent.parent.parent / "bin" # 调整路径层级
|
||||
# 创建目标目录路径
|
||||
netrans_path = tmp_path / "bin"
|
||||
|
||||
# 执行目录复制
|
||||
shutil.copytree(
|
||||
src=str(source_dir),
|
||||
dst=str(netrans_path),
|
||||
symlinks=True,
|
||||
ignore_dangling_symlinks=True
|
||||
)
|
||||
return netrans_path
|
||||
|
||||
@pytest.fixture
|
||||
def netrans_instance(mock_model_dir, mock_netrans_path):
|
||||
return Netrans(str(mock_model_dir), netrans=str(mock_netrans_path))
|
||||
|
||||
class TestNetransInitialization:
|
||||
|
||||
def test_init_with_default_netrans(self, mock_model_dir):
|
||||
# 测试能否找到默认的netrans(.bashrc NETRANS_PATH)
|
||||
net = Netrans(str(mock_model_dir))
|
||||
assert net.model_path == str(mock_model_dir)
|
||||
assert hasattr(net, 'netrans_path')
|
||||
|
||||
def test_init_with_custom_netrans(self, mock_model_dir, mock_netrans_path):
|
||||
# 测试传参 netrans
|
||||
net = Netrans(str(mock_model_dir), netrans= str(mock_netrans_path))
|
||||
assert net.netrans_path == str(mock_netrans_path)
|
||||
|
||||
def test_init_with_invalid_model_path(self):
|
||||
# 测试给定非法路径报错
|
||||
with pytest.raises(FileNotFoundError):
|
||||
Netrans("invalid/path")
|
||||
|
||||
def test_load_success(self, netrans_instance, tmp_path):
|
||||
# 测试模型导入功能
|
||||
with patch('subprocess.run') as mock_run:
|
||||
netrans_instance.load()
|
||||
mock_run.assert_called_once()
|
||||
|
||||
# 验证生成的文件
|
||||
output_dir = Path(netrans_instance.model_path)
|
||||
assert (output_dir / f"{netrans_instance.model_name}.json").exists()
|
||||
assert (output_dir / f"{netrans_instance.model_name}.data").exists()
|
||||
|
||||
def test_load_failure(self, netrans_instance):
|
||||
with patch('subprocess.run', side_effect=Exception("Process error")):
|
||||
with pytest.raises(RuntimeError):
|
||||
netrans_instance.load()
|
||||
|
||||
# @pytest.mark.parametrize("inputmeta_param, expected", [
|
||||
# (False, "generate_template"),
|
||||
# (True, "auto_detect"),
|
||||
# (netrans_instance.model_path/f"{netrans_instance.model_name}_inputmeta.yml", "use_custom")
|
||||
# ])
|
||||
# def test_config_gen(self, netrans_instance, inputmeta_param, expected):
|
||||
# with patch.object(Netrans, '_handle_inputmeta') as mock_method:
|
||||
# netrans_instance.config(inputmeta=inputmeta_param)
|
||||
# mock_method.assert_called_with(expected)
|
||||
|
||||
def test_config_gen_inputmeta(self, netrans_instance):
|
||||
|
||||
with patch('subprocess.run') as mock_run:
|
||||
netrans_instance.config()
|
||||
mock_run.assert_called_once()
|
||||
assert (Path(netrans_instance.model_path) / f"{netrans_instance.model_name}_inputmeta.yml").exists()
|
||||
|
||||
|
||||
def test_config_auto_find_inputmeta(self, netrans_instance):
|
||||
|
||||
with patch('subprocess.run') as mock_run:
|
||||
netrans_instance.config(True)
|
||||
|
||||
assert netrans_instance.input_meta == str(Path(netrans_instance.model_path) / f"{netrans_instance.model_name}_inputmeta.yml")
|
||||
|
||||
def test_config_use_costume_inputmeta(self, netrans_instance):
|
||||
|
||||
inputmeta = str(Path(netrans_instance.model_path) / f"{netrans_instance.model_name}_inputmeta.yml")
|
||||
cp_file = inputmeta+'.tmp.yml'
|
||||
shutil.copy2(str(inputmeta), str(cp_file))
|
||||
|
||||
netrans_instance.config(inputmeta=cp_file)
|
||||
assert netrans_instance.input_meta == cp_file
|
||||
|
||||
|
||||
def test_config_with_invalid_model_path(self, netrans_instance):
|
||||
# with patch('subprocess.run', side_effect=Exception("Process error")):
|
||||
# with pytest.raises(RuntimeError):
|
||||
# netrans_instance.config(False)
|
||||
# 测试给定非法路径报错
|
||||
with pytest.raises(FileExistsError):
|
||||
inputmeta="invalid/path"
|
||||
print(isinstance(inputmeta, str))
|
||||
netrans_instance.config(inputmeta="invalid/path")
|
||||
|
||||
def test_config_parameter_combinations(self, netrans_instance):
|
||||
test_params = {
|
||||
'scale': [[0, 1, 0.5], [0.1, 0.2, 0.3]],
|
||||
'mean': [[0, 0, 128], [125, 127, 128]],
|
||||
'reverse_channel': [True, False]
|
||||
}
|
||||
for scale,mean in zip(test_params['scale'],test_params['mean']):
|
||||
for reverse in test_params['reverse_channel']:
|
||||
netrans_instance.config(
|
||||
scale=scale,
|
||||
mean=mean,
|
||||
reverse_channel=reverse
|
||||
)
|
||||
data = netrans_instance._verify_preprocess_value()
|
||||
assert data['scale'] == scale
|
||||
assert data['mean'] == mean
|
||||
assert data['reverse_channel'] == reverse
|
||||
|
||||
def test_valid_quantize_types(self, netrans_instance):
|
||||
test_params = ["uint8", "int8", "int16"]
|
||||
for qtype in test_params:
|
||||
netrans_instance.quantize(qtype)
|
||||
assert netrans_instance.quantize_type == qtype
|
||||
|
||||
def test_invalid_quantize_type(self, netrans_instance):
|
||||
with pytest.raises(TypeError):
|
||||
netrans_instance.quantize("float32")
|
||||
|
||||
def test_quantize(self, netrans_instance):
|
||||
netrans_instance.quantize('uint8')
|
||||
assert (Path(netrans_instance.model_path) / f"{netrans_instance.model_name}_asymmetric_affine.quantize").exists()
|
||||
|
||||
def test_export(self, netrans_instance):
|
||||
# netrans_instance.quantize('uint8')
|
||||
netrans_instance.export(quantize_type='uint8')
|
||||
assert (Path(netrans_instance.model_path) / "wksp/asymmetric_affine/network_binary.nb").exists()
|
||||
|
||||
|
||||
# class TestExportMethod:
|
||||
# def test_export_flow(self, netrans_instance):
|
||||
# with patch.multiple(Netrans,
|
||||
# _validate_quant_config=Mock(),
|
||||
# _compile_model=Mock()) as mocks:
|
||||
# netrans_instance.export()
|
||||
# mocks['_validate_quant_config'].assert_called_once()
|
||||
# mocks['_compile_model'].assert_called_once()
|
||||
|
||||
# class TestModel2NBG:
|
||||
# @pytest.mark.parametrize("params", [
|
||||
# {'quantize_type': 'uint8'},
|
||||
# {'quantize_type': 'int8', 'mean': 128, 'scale': 0.0039},
|
||||
# {'quantize_type': 'int16', 'mean': [128,127,125], 'scale': 0.0039, 'reverse_channel': True},
|
||||
# {'quantize_type': 'uint8', 'inputmeta': True}
|
||||
# ])
|
||||
# def test_full_workflow(self, netrans_instance, params):
|
||||
# with patch.multiple(Netrans,
|
||||
# import=Mock(),
|
||||
# config=Mock(),
|
||||
# quantize=Mock(),
|
||||
# export=Mock()) as mocks:
|
||||
# netrans_instance.model2nbg(**params)
|
||||
|
||||
# if 'inputmeta' not in params or params['inputmeta'] is not True:
|
||||
# mocks['config'].assert_called_with(
|
||||
# mean=params.get('mean'),
|
||||
# scale=params.get('scale'),
|
||||
# reverse_channel=params.get('reverse_channel'),
|
||||
# inputmeta=params.get('inputmeta', False)
|
||||
# )
|
||||
|
||||
# mocks['quantize'].assert_called_with(params['quantize_type'])
|
||||
# mocks['export'].assert_called_once()
|
||||
|
||||
# 代码覆盖率配置(pytest.ini)
|
||||
"""
|
||||
[pytest]
|
||||
addopts = --cov=nertans --cov-report=term-missing
|
||||
"""
|
Loading…
Reference in New Issue