Part of the fixture moved to the conftest file (#6523)

* Part of the fixture moved to the conftest file

Signed-off-by: wangting0128 <ting.wang@zilliz.com>

* Update README_CN.md file

Signed-off-by: wangting0128 <ting.wang@zilliz.com>

* Update index case

Signed-off-by: wangting0128 <ting.wang@zilliz.com>
This commit is contained in:
紫晴 2021-07-15 15:03:54 +08:00 committed by GitHub
parent 7b9f0d398f
commit b082cda2ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 151 additions and 134 deletions

View File

@ -98,7 +98,7 @@
<p>&nbsp;</p>
<h3 >模块介绍</h3>
<p><strong>模块调用关系图</strong></p>
<p><img src="https://zilliverse.feishu.cn/space/api/box/stream/download/asynccode/?code=N2UzZWQxYzRmM2M1MjdlZjdiN2YwMDM2MGUzNDRhM2NfSkNRM3ZxUVRyaDJoQzhQOXh0U2pPZ3RpQ1FUYmdIQW9fVG9rZW46Ym94Y24xZjJBU0ZhTkpMVFNtbm5OQU5uZ09jXzE2MjYyNTkzMzc6MTYyNjI2MjkzN19WNA" referrerpolicy="no-referrer" alt="img"></p>
<p><img src="https://github.com/milvus-io/milvus/blob/master/tests20/python_client/graphs/module_call_diagram.jpg" referrerpolicy="no-referrer" alt="img"></p>
<h5 > 工作目录及文件介绍</h5>
<ul>
<li><strong>base</strong>:放置已封装好的 <strong>pymilvus-orm 模块文件</strong>,以及 pytest 框架的 setup 和 teardown 处理等</li>
@ -129,8 +129,7 @@
<p>&nbsp;</p>
<h5 >Python 测试代码添加注意事项</h5>
<ol>
<li><h6 >测试编码风格</h6>
</li>
<h6 >1. 测试编码风格</h6>
</ol>
<ul>
@ -198,8 +197,7 @@
</ul>
<ol>
<li><h6 >编码注意事项</h6>
</li>
<h6 >2. 编码注意事项</h6>
</ol>
<ul>
@ -250,8 +248,7 @@ self.partition_wrap.init_partition(collection=None, name=partition_name, check_t
partition_w = self.init_partition_wrap(collection_w, partition_name, check_task=CheckTasks.check_partition_property, check_items={&quot;name&quot;: partition_name, &quot;description&quot;: description, &quot;is_empty&quot;: True, &quot;num_entities&quot;: 0})
</code></pre>
<ol>
<li><h6 >测试用例添加</h6>
</li>
<h6 >3. 测试用例添加</h6>
</ol>
<ul>
@ -292,17 +289,11 @@ partition_w = self.init_partition_wrap(collection_w, partition_name, check_task=
</ul>
<pre><code>self.connection_wrap = ApiConnectionsWrapper()
self.utility_wrap = ApiUtilityWrapper()
self.collection_wrap = ApiCollectionWrapper()
self.partition_wrap = ApiPartitionWrapper()
self.index_wrap = ApiIndexWrapper()
self.collection_schema_wrap = ApiCollectionSchemaWrapper()
self.field_schema_wrap = ApiFieldSchemaWrapper()
</code></pre>
<ul>
@ -318,12 +309,11 @@ self.field_schema_wrap = ApiFieldSchemaWrapper()
</ul>
<ol>
<li><h6 >框架功能添加</h6>
</li>
<h6 >4. 框架功能添加</h6>
</ol>
<ul>
<li>在 utils 目录下添加需要的全局方法或者工具</li>
<li>可将相应的配置内容加入 config 目录下</li>
</ul>

View File

@ -9,12 +9,9 @@ from base.partition_wrapper import ApiPartitionWrapper
from base.index_wrapper import ApiIndexWrapper
from base.utility_wrapper import ApiUtilityWrapper
from base.schema_wrapper import ApiCollectionSchemaWrapper, ApiFieldSchemaWrapper
from config.log_config import log_config
from utils.util_log import test_log as log
from common import common_func as cf
from common import common_type as ct
from check.param_check import ip_check, number_check
class ParamInfo:
@ -48,11 +45,10 @@ class Base:
def teardown_class(self):
log.info("[teardown_class] Start teardown class...")
pass
def setup_method(self, method):
log.info(("*" * 35) + " setup " + ("*" * 35))
log.info("[setup_method] Start setup test case %s..." % method.__name__)
log.info("[setup_method] Start setup test case %s." % method.__name__)
self.connection_wrap = ApiConnectionsWrapper()
self.utility_wrap = ApiUtilityWrapper()
self.collection_wrap = ApiCollectionWrapper()
@ -74,9 +70,9 @@ class Base:
if self.collection_wrap.collection is not None:
self.collection_wrap.drop(check_task=ct.CheckTasks.check_nothing)
collection_list = self.utility_wrap.list_collections()[0]
for collection_object in self.collection_object_list:
if collection_object.collection is not None \
and collection_object.name in self.utility_wrap.list_collections()[0]:
if collection_object.collection is not None and collection_object.name in collection_list:
collection_object.drop(check_task=ct.CheckTasks.check_nothing)
except Exception as e:
@ -94,24 +90,6 @@ class Base:
except Exception as e:
log.debug(str(e))
@pytest.fixture(scope="module", autouse=True)
def initialize_env(self, request):
""" clean log before testing """
host = request.config.getoption("--host")
port = request.config.getoption("--port")
handler = request.config.getoption("--handler")
clean_log = request.config.getoption("--clean_log")
""" params check """
assert ip_check(host) and number_check(port)
""" modify log files """
cf.modify_file(file_path_list=[log_config.log_debug, log_config.log_info, log_config.log_err], is_modify=clean_log)
log.info("#" * 80)
log.info("[initialize_milvus] Log cleaned up, start testing...")
param_info.prepare_param_info(host, port, handler)
class TestcaseBase(Base):
"""
@ -183,3 +161,22 @@ class TestcaseBase(Base):
collection_w.load()
return collection_w, vectors, binary_raw_vectors, insert_ids
def insert_entities_into_two_partitions_in_half(self, half, prefix='query'):
"""
insert default entities into two partitions(partition_w and _default) in half(int64 and float fields values)
:param half: half of nb
:return: collection wrap and partition wrap
"""
conn = self._connect()
collection_w = self.init_collection_wrap(name=cf.gen_unique_str(prefix))
partition_w = self.init_partition_wrap(collection_wrap=collection_w)
# insert [0, half) into partition_w
df_partition = cf.gen_default_dataframe_data(nb=half, start=0)
partition_w.insert(df_partition)
# insert [half, nb) into _default
df_default = cf.gen_default_dataframe_data(nb=half, start=half)
collection_w.insert(df_default)
conn.flush([collection_w.name])
collection_w.load()
return collection_w, partition_w, df_partition, df_default

View File

@ -26,24 +26,31 @@ class ResponseChecker:
"""
result = True
if self.check_task is None:
# Interface normal return check
result = self.assert_succ(self.succ, True)
elif self.check_task == CheckTasks.err_res:
# Interface return error code and error message check
result = self.assert_exception(self.response, self.succ, self.check_items)
elif self.check_task == CheckTasks.ccr:
# Connection interface response check
result = self.check_value_equal(self.response, self.func_name, self.check_items)
elif self.check_task == CheckTasks.check_collection_property:
# Collection interface response check
result = self.check_collection_property(self.response, self.func_name, self.check_items)
elif self.check_task == CheckTasks.check_partition_property:
# Partition interface response check
result = self.check_partition_property(self.response, self.func_name, self.check_items)
elif self.check_task == CheckTasks.check_search_results:
# Search interface of collection and partition that response check
result = self.check_search_results(self.response, self.func_name, self.check_items)
elif self.check_task == CheckTasks.check_query_results:
# Query interface of collection and partition that response check
result = self.check_query_results(self.response, self.func_name, self.check_items)
# Add check_items here if something new need verify

View File

@ -90,6 +90,7 @@ def list_equal_check(param1, param2):
return check_result
def list_contain_check(sublist, superlist):
if not isinstance(sublist, list):
raise Exception("%s isn't list type" % sublist)
@ -109,6 +110,7 @@ def list_contain_check(sublist, superlist):
return check_result
def get_connect_object_name(_list):
""" get the name of the objects that returned by the connection """
if not isinstance(_list, list):

View File

@ -24,3 +24,11 @@ class ConnectionErrorMessage(ExceptionsMessage):
class CollectionErrorMessage(ExceptionsMessage):
CollNotLoaded = "collection %s was not loaded into memory"
class PartitionErrorMessage(ExceptionsMessage):
pass
class IndexErrorMessage(ExceptionsMessage):
WrongFieldName = "%s has type %s, but expected one of: bytes, unicode"

View File

@ -2,6 +2,10 @@ import pytest
import common.common_type as ct
import common.common_func as cf
from utils.util_log import test_log as log
from base.client_base import param_info
from check.param_check import ip_check, number_check
from config.log_config import log_config
def pytest_addoption(parser):
@ -25,6 +29,7 @@ def pytest_addoption(parser):
parser.addoption('--err_msg', action='store', default="err_msg", help="error message of test")
parser.addoption('--term_expr', action='store', default="term_expr", help="expr of query quest")
parser.addoption('--check_content', action='store', default="check_content", help="content of check")
parser.addoption('--field_name', action='store', default="field_name", help="field_name of index")
@pytest.fixture
@ -124,12 +129,38 @@ def term_expr(request):
@pytest.fixture
def check_content(request):
log.error("^" * 50)
log.error("check_content")
return request.config.getoption("--check_content")
@pytest.fixture
def field_name(request):
return request.config.getoption("--field_name")
""" fixture func """
@pytest.fixture(scope="session", autouse=True)
def initialize_env(request):
""" clean log before testing """
host = request.config.getoption("--host")
port = request.config.getoption("--port")
handler = request.config.getoption("--handler")
clean_log = request.config.getoption("--clean_log")
""" params check """
assert ip_check(host) and number_check(port)
""" modify log files """
cf.modify_file(file_path_list=[log_config.log_debug, log_config.log_info, log_config.log_err], is_modify=clean_log)
log.info("#" * 80)
log.info("[initialize_milvus] Log cleaned up, start testing...")
param_info.prepare_param_info(host, port, handler)
@pytest.fixture(params=ct.get_invalid_strs)
def get_invalid_string(request):
yield request.param
@ -138,3 +169,31 @@ def get_invalid_string(request):
@pytest.fixture(params=cf.gen_simple_index())
def get_index_param(request):
yield request.param
@pytest.fixture(params=ct.get_invalid_strs)
def get_invalid_collection_name(request):
yield request.param
@pytest.fixture(params=ct.get_invalid_strs)
def get_invalid_field_name(request):
yield request.param
@pytest.fixture(params=ct.get_invalid_strs)
def get_invalid_index_type(request):
yield request.param
# TODO: construct invalid index params for all index types
@pytest.fixture(params=[{"metric_type": "L3", "index_type": "IVF_FLAT"},
{"metric_type": "L2", "index_type": "IVF_FLAT", "err_params": {"nlist": 10}},
{"metric_type": "L2", "index_type": "IVF_FLAT", "params": {"nlist": -1}}])
def get_invalid_index_params(request):
yield request.param
@pytest.fixture(params=ct.get_invalid_strs)
def get_invalid_partition_name(request):
yield request.param

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

View File

@ -1,6 +1,7 @@
[pytest]
addopts = --host 10.98.0.7 --html=/tmp/ci_logs/report.html --self-contained-html -v
addopts = --host 172.20.255.155 --html=/milvus/tests20/python_client/report.html --self-contained-html
# -;addopts = --host 172.28.255.155 --html=/tmp/report.html
# python3 -W ignore -m pytest

View File

@ -5,11 +5,12 @@ from pymilvus_orm import FieldSchema
from base.client_base import TestcaseBase
from base.index_wrapper import ApiIndexWrapper
from base.collection_wrapper import ApiCollectionWrapper
from utils.util_log import test_log as log
from common import common_func as cf
from common import common_type as ct
from common.common_type import CaseLabel, CheckTasks
from common.code_mapping import CollectionErrorMessage as clem
from common.code_mapping import IndexErrorMessage as iem
prefix = "index"
default_schema = cf.gen_default_collection_schema()
@ -20,39 +21,6 @@ default_index_params = {"index_type": "IVF_SQ8", "metric_type": "L2", "params":
class TestIndexParams(TestcaseBase):
""" Test case of index interface """
@pytest.fixture(
scope="function",
params=ct.get_invalid_strs
)
def get_invalid_collection_name(self, request):
yield request.param
@pytest.fixture(
scope="function",
params=ct.get_invalid_strs
)
def get_invalid_field_name(self, request):
yield request.param
@pytest.fixture(
scope="function",
params=ct.get_invalid_strs
)
def get_invalid_index_type(self, request):
yield request.param
# TODO: construct invalid index params for all index types
@pytest.fixture(
scope="function",
params=[
{"metric_type": "L3", "index_type": "IVF_FLAT"},
{"metric_type": "L2", "index_type": "IVF_FLAT", "err_params": {"nlist": 10}},
{"metric_type": "L2", "index_type": "IVF_FLAT", "params": {"nlist": -1}},
]
)
def get_invalid_index_params(self, request):
yield request.param
# @pytest.mark.xfail(reason="issue #5646")
@pytest.mark.tags(CaseLabel.L1)
def test_index_collection_None(self):
@ -61,22 +29,30 @@ class TestIndexParams(TestcaseBase):
method: input none collection object
expected: raise exception
"""
self._connect()
self.index_wrap.init_index(None, default_field_name, default_index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": "Collection"})
check_items={ct.err_code: 0, ct.err_msg: clem.CollectionType})
@pytest.mark.tags(CaseLabel.L1)
def test_index_field_name_invalid(self, get_invalid_field_name):
@pytest.mark.parametrize("field_name", ct.get_invalid_strs)
def test_index_field_name_invalid(self, field_name):
"""
target: test index with error field name
method: input field name
expected: raise exception
"""
f_name = get_invalid_field_name
c_name = cf.gen_unique_str(prefix)
collection_w = self.init_collection_wrap(name=c_name)
self.index_wrap.init_index(collection_w.collection, f_name, default_index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": "but expected one of"})
collection_name = cf.gen_unique_str(prefix)
collection_w = self.init_collection_wrap(name=collection_name)
log.error(iem.WrongFieldName % (str(field_name), type(field_name)))
self.index_wrap.init_index(collection_w.collection, field_name, default_index_params,
check_task=CheckTasks.err_res,
check_items={ct.err_code: 1,
ct.err_msg: iem.WrongFieldName % (str(field_name),
type(field_name).__name__)})
@pytest.mark.tags(CaseLabel.L1)
def test_index_field_name_not_existed(self):
@ -89,7 +65,7 @@ class TestIndexParams(TestcaseBase):
f_name = cf.gen_unique_str(prefix)
collection_w = self.init_collection_wrap(name=c_name)
self.index_wrap.init_index(collection_w.collection, f_name, default_index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": "CreateIndex failed"})
check_items={ct.err_code: 1, ct.err_msg: "CreateIndex failed"})
# TODO: update eror msg
@pytest.mark.tags(CaseLabel.L1)
@ -108,7 +84,7 @@ class TestIndexParams(TestcaseBase):
else:
msg = "Invalid index_type"
self.index_wrap.init_index(collection_w.collection, default_field_name, index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": msg})
check_items={ct.err_code: 1, ct.err_msg: msg})
@pytest.mark.tags(CaseLabel.L1)
def test_index_type_not_supported(self):
@ -122,7 +98,7 @@ class TestIndexParams(TestcaseBase):
index_params = copy.deepcopy(default_index_params)
index_params["index_type"] = "IVFFFFFFF"
self.index_wrap.init_index(collection_w.collection, default_field_name, index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": ""})
check_items={ct.err_code: 1, ct.err_msg: ""})
@pytest.mark.tags(CaseLabel.L1)
def test_index_params_invalid(self, get_invalid_index_params):
@ -135,7 +111,7 @@ class TestIndexParams(TestcaseBase):
collection_w = self.init_collection_wrap(name=c_name)
index_params = get_invalid_index_params
self.index_wrap.init_index(collection_w.collection, default_field_name, index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": ""})
check_items={ct.err_code: 1, ct.err_msg: ""})
# TODO: not supported
@pytest.mark.tags(CaseLabel.L1)
@ -149,21 +125,11 @@ class TestIndexParams(TestcaseBase):
index_name = get_invalid_index_name
collection_w = self.init_collection_wrap(name=c_name)
self.index_wrap.init_index(collection_w.collection, default_field_name, default_index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": ""})
check_items={ct.err_code: 1, ct.err_msg: ""})
class TestIndexBase(TestcaseBase):
""" Test case of index interface """
# TODO: construct valid index params for all index types
@pytest.fixture(
scope="function",
params=[
default_index_params,
]
)
def get_valid_index_params(self, request):
yield request.param
@pytest.mark.tags(CaseLabel.L1)
def test_index_collection_empty(self):
@ -179,7 +145,8 @@ class TestIndexBase(TestcaseBase):
cf.assert_equal_index(index, collection_w.collection.indexes[0])
@pytest.mark.tags(CaseLabel.L1)
def test_index_params(self, get_valid_index_params):
@pytest.mark.parametrize("index_param", [default_index_params])
def test_index_params(self, index_param):
"""
target: test index with all index type/params
method: input valid params
@ -189,7 +156,7 @@ class TestIndexBase(TestcaseBase):
collection_w = self.init_collection_wrap(name=c_name)
data = cf.gen_default_list_data(ct.default_nb)
collection_w.insert(data=data)
index_params = get_valid_index_params
index_params = index_param
index, _ = self.index_wrap.init_index(collection_w.collection, default_field_name, index_params)
# TODO: assert index
cf.assert_equal_index(index, collection_w.collection.indexes[0])
@ -224,7 +191,7 @@ class TestIndexBase(TestcaseBase):
collection_w = self.init_collection_wrap(name=c_name)
collection_w.collection.create_index(default_field_name, default_index_params, index_name=index_name)
self.index_wrap.init_index(collection_w.collection, default_field_name, default_index_params, check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": ""})
check_items={ct.err_code: 1, ct.err_msg: ""})
# TODO: server not supported
@pytest.mark.tags(CaseLabel.L1)
@ -302,7 +269,7 @@ class TestIndexBase(TestcaseBase):
_, _ = self.index_wrap.init_index(collection_w.collection, default_field_name, default_index_params)
self.index_wrap.drop()
self.index_wrap.drop(check_task=CheckTasks.err_res,
check_items={"err_code": 1, "err_msg": "Index doesn't exist"})
check_items={ct.err_code: 1, ct.err_msg: "Index doesn't exist"})
class TestIndexAdvanced(TestcaseBase):

View File

@ -705,22 +705,21 @@ class TestQueryOperation(TestcaseBase):
assert len(res) == 1
assert res[0][ct.default_int64_field_name] == half
@pytest.mark.tags(ct.CaseLabel.L2)
def insert_entities_into_two_partitions_in_half(self, half):
"""
insert default entities into two partitions(partition_w and _default) in half(int64 and float fields values)
:param half: half of nb
:return: collection wrap and partition wrap
"""
conn = self._connect()
collection_w = self.init_collection_wrap(name=cf.gen_unique_str(prefix))
partition_w = self.init_partition_wrap(collection_wrap=collection_w)
# insert [0, half) into partition_w
df_partition = cf.gen_default_dataframe_data(nb=half, start=0)
partition_w.insert(df_partition)
# insert [half, nb) into _default
df_default = cf.gen_default_dataframe_data(nb=half, start=half)
collection_w.insert(df_default)
conn.flush([collection_w.name])
collection_w.load()
return collection_w, partition_w, df_partition, df_default
# def insert_entities_into_two_partitions_in_half(self, half):
# """
# insert default entities into two partitions(partition_w and _default) in half(int64 and float fields values)
# :param half: half of nb
# :return: collection wrap and partition wrap
# """
# conn = self._connect()
# collection_w = self.init_collection_wrap(name=cf.gen_unique_str(prefix))
# partition_w = self.init_partition_wrap(collection_wrap=collection_w)
# # insert [0, half) into partition_w
# df_partition = cf.gen_default_dataframe_data(nb=half, start=0)
# partition_w.insert(df_partition)
# # insert [half, nb) into _default
# df_default = cf.gen_default_dataframe_data(nb=half, start=half)
# collection_w.insert(df_default)
# conn.flush([collection_w.name])
# collection_w.load()
# return collection_w, partition_w, df_partition, df_default

View File

@ -15,19 +15,6 @@ default_index_params = {"index_type": "IVF_SQ8", "metric_type": "L2", "params":
class TestUtilityParams(TestcaseBase):
""" Test case of index interface """
@pytest.fixture(
scope="function",
params=ct.get_invalid_strs
)
def get_invalid_collection_name(self, request):
yield request.param
@pytest.fixture(
scope="function",
params=ct.get_invalid_strs
)
def get_invalid_partition_name(self, request):
yield request.param
@pytest.mark.tags(CaseLabel.L1)
def test_has_collection_name_invalid(self, get_invalid_collection_name):