diff --git a/tests20/python_client/README_CN.md b/tests20/python_client/README_CN.md
index d6da3be8c5..71a957b2be 100644
--- a/tests20/python_client/README_CN.md
+++ b/tests20/python_client/README_CN.md
@@ -98,7 +98,7 @@
模块介绍
模块调用关系图
-
+
工作目录及文件介绍
- base:放置已封装好的 pymilvus-orm 模块文件,以及 pytest 框架的 setup 和 teardown 处理等
@@ -129,8 +129,7 @@
Python 测试代码添加注意事项
-测试编码风格
-
+1. 测试编码风格
-编码注意事项
-
+2. 编码注意事项
@@ -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={"name": partition_name, "description": description, "is_empty": True, "num_entities": 0})
-测试用例添加
-
+3. 测试用例添加
@@ -292,17 +289,11 @@ partition_w = self.init_partition_wrap(collection_w, partition_name, check_task=
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()
@@ -318,12 +309,11 @@ self.field_schema_wrap = ApiFieldSchemaWrapper()
-框架功能添加
-
+4. 框架功能添加
- 在 utils 目录下添加需要的全局方法或者工具
- 可将相应的配置内容加入 config 目录下
-
+
diff --git a/tests20/python_client/base/client_base.py b/tests20/python_client/base/client_base.py
index 72a2e5f247..ab4fdc14f6 100644
--- a/tests20/python_client/base/client_base.py
+++ b/tests20/python_client/base/client_base.py
@@ -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
diff --git a/tests20/python_client/check/func_check.py b/tests20/python_client/check/func_check.py
index 73d2e443be..2ccf4c5344 100644
--- a/tests20/python_client/check/func_check.py
+++ b/tests20/python_client/check/func_check.py
@@ -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
diff --git a/tests20/python_client/check/param_check.py b/tests20/python_client/check/param_check.py
index a7cac3e474..ff989ce7b2 100644
--- a/tests20/python_client/check/param_check.py
+++ b/tests20/python_client/check/param_check.py
@@ -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):
diff --git a/tests20/python_client/common/code_mapping.py b/tests20/python_client/common/code_mapping.py
index 59c1c7261b..b75265f758 100644
--- a/tests20/python_client/common/code_mapping.py
+++ b/tests20/python_client/common/code_mapping.py
@@ -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"
diff --git a/tests20/python_client/conftest.py b/tests20/python_client/conftest.py
index 3092b0029b..210615cd66 100644
--- a/tests20/python_client/conftest.py
+++ b/tests20/python_client/conftest.py
@@ -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
diff --git a/tests20/python_client/graphs/module_call_diagram.jpg b/tests20/python_client/graphs/module_call_diagram.jpg
new file mode 100644
index 0000000000..37286e04ac
Binary files /dev/null and b/tests20/python_client/graphs/module_call_diagram.jpg differ
diff --git a/tests20/python_client/pytest.ini b/tests20/python_client/pytest.ini
index a77ce13cfe..1a892e5021 100644
--- a/tests20/python_client/pytest.ini
+++ b/tests20/python_client/pytest.ini
@@ -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
diff --git a/tests20/python_client/testcases/test_index.py b/tests20/python_client/testcases/test_index.py
index 0180558df8..036bf956db 100644
--- a/tests20/python_client/testcases/test_index.py
+++ b/tests20/python_client/testcases/test_index.py
@@ -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):
diff --git a/tests20/python_client/testcases/test_query.py b/tests20/python_client/testcases/test_query.py
index ac4cdbc83c..400c782ba6 100644
--- a/tests20/python_client/testcases/test_query.py
+++ b/tests20/python_client/testcases/test_query.py
@@ -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
diff --git a/tests20/python_client/testcases/test_utility.py b/tests20/python_client/testcases/test_utility.py
index 21297952e0..8f60387eec 100644
--- a/tests20/python_client/testcases/test_utility.py
+++ b/tests20/python_client/testcases/test_utility.py
@@ -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):