diff --git a/README_for_developer.md b/README_for_developer.md index eca9fc40..f6aad97e 100644 --- a/README_for_developer.md +++ b/README_for_developer.md @@ -46,15 +46,22 @@ $ make lint ## Test -### テストの実行 -1. AnnoFabの認証情報を`.netrc`に記載する。 -2. `pytest.ini`にテスト対象の`project_id`を指定する。**【注意】テストを実行すると、AnnoFabプロジェクトの内容が変更される** +### テストの実行方法 +1. AnnoFabの認証情報を、`.netrc`ファイルまたは環境変数に設定する。 +2. `pytest.ini`に、テスト対象の`project_id`と`task_id`を指定する。 + * `task_id`はプロジェクト`project_id`配下であること + * **【注意】テストを実行すると、AnnoFabプロジェクトの内容が変更される** 3. `$ make test`コマンドを実行する。 -#### 直接pytestを実行する場合 +#### タスクの前提条件 +* タスクの先頭画像にアノテーションが1個以上付与されている +* タスクの先頭画像に検査コメントが1個以上付与されている + + +#### テストメソッドを指定してテストする方法 ``` -$ poetry run pytest tests +$ poetry run pytest tests/test_api.py::TestLogin::test_login ``` annofabapiでは、pytestのカスタムオプションを定義しています。 diff --git a/annofabapi/__init__.py b/annofabapi/__init__.py index da3ac0c6..2328d302 100644 --- a/annofabapi/__init__.py +++ b/annofabapi/__init__.py @@ -1,7 +1,7 @@ from annofabapi.api import AnnofabApi from annofabapi.api2 import AnnofabApi2 from annofabapi.wrapper import Wrapper -from annofabapi.resource import build, build_from_netrc, build_from_env, build_from_netrc_or_env, Resource +from annofabapi.resource import build, build_from_netrc, build_from_env, Resource from .__version__ import __version__ @@ -11,7 +11,6 @@ "Wrapper", "build", "build_from_netrc", - "build_from_netrc_or_env", "build_from_env", "Resource", "__version__", diff --git a/annofabapi/api.py b/annofabapi/api.py index c2db4f78..daa928f7 100644 --- a/annofabapi/api.py +++ b/annofabapi/api.py @@ -97,6 +97,8 @@ def __init__(self, login_user_id: str, login_password: str, endpoint_url: str = #: Signed Cookie情報 cookies: Optional[RequestsCookieJar] = None + __account_id: Optional[str] = None + class __MyToken(AuthBase): """ requestsモジュールのauthに渡す情報。 @@ -413,3 +415,19 @@ def delete_labor_control(self, data_id: str) -> Tuple[Any, requests.Response]: http_method = "DELETE" keyword_params: Dict[str, Any] = {} return self._request_wrapper(http_method, url_path, **keyword_params) + + ######################################### + # Public Method : Other + ######################################### + @property + def account_id(self) -> str: + """ + AnnoFabにログインするユーザのaccount_id + """ + if self.__account_id is not None: + return self.__account_id + else: + content, _ = self.get_my_account() + account_id = content["account_id"] + self.__account_id = account_id + return account_id diff --git a/annofabapi/resource.py b/annofabapi/resource.py index ec4cc663..18ceb576 100644 --- a/annofabapi/resource.py +++ b/annofabapi/resource.py @@ -1,6 +1,7 @@ import logging import netrc import os +from typing import Optional from urllib.parse import urlparse from annofabapi import AnnofabApi, AnnofabApi2, Wrapper @@ -32,10 +33,17 @@ def __init__(self, login_user_id: str, login_password: str, endpoint_url: str = self.api2 = AnnofabApi2(self.api) -def build(login_user_id: str, login_password: str, endpoint_url: str = DEFAULT_ENDPOINT_URL) -> Resource: +def build( + login_user_id: Optional[str] = None, login_password: Optional[str] = None, endpoint_url: str = DEFAULT_ENDPOINT_URL +) -> Resource: """ AnnofabApi, Wrapperのインスタンスを保持するインスタンスを生成する。 + ``login_user_id``と``login_password`の両方がNoneの場合は、`.netrc`ファイルまたは環境変数から認証情報を取得する。 + 認証情報は、`.netrc`ファイル、環境変数の順に読み込む。 + + 環境変数は``ANNOFAB_USER_ID`` , ``ANNOFAB_PASSWORD`` を参照する。 + Args: login_user_id: AnnoFabにログインするときのユーザID login_password: AnnoFabにログインするときのパスワード @@ -45,7 +53,24 @@ def build(login_user_id: str, login_password: str, endpoint_url: str = DEFAULT_E AnnofabApi, Wrapperのインスタンスを保持するインスタンス """ - return Resource(login_user_id, login_password, endpoint_url=endpoint_url) + if login_user_id is not None and login_password is not None: + return Resource(login_user_id, login_password, endpoint_url=endpoint_url) + + elif login_user_id is None and login_password is None: + try: + return build_from_netrc(endpoint_url) + except AnnofabApiException: + pass + + try: + return build_from_env(endpoint_url) + except AnnofabApiException: + pass + + raise AnnofabApiException("`.netrc`ファイルまたは環境変数にAnnoFab認証情報はありませんでした。") + + else: + raise ValueError() def build_from_netrc(endpoint_url: str = DEFAULT_ENDPOINT_URL) -> Resource: @@ -97,29 +122,3 @@ def build_from_env(endpoint_url: str = DEFAULT_ENDPOINT_URL) -> Resource: logger.debug("環境変数からAnnoFab認証情報を読み込みました。") return Resource(login_user_id, login_password, endpoint_url=endpoint_url) - - -def build_from_netrc_or_env(endpoint_url: str = DEFAULT_ENDPOINT_URL) -> Resource: - """ - `.netrc`ファイルまたは環境変数からAnnoFab認証情報を取得し、annnofabapi.Resourceインスタンスを生成します。 - netrc, 環境変数の順に認証情報を読み込みます。 - - Args: - endpoint_url: - - Returns: - - """ - # '.netrc'ファイルから認証情報を取得する - try: - return build_from_netrc(endpoint_url) - except AnnofabApiException: - pass - - # 環境変数から認証情報を取得する - try: - return build_from_env(endpoint_url) - except AnnofabApiException: - pass - - raise AnnofabApiException("`.netrc`ファイルまたは環境変数にAnnoFab認証情報はありませんでした。") diff --git a/pytest.ini b/pytest.ini index 543a54ee..a66d8820 100644 --- a/pytest.ini +++ b/pytest.ini @@ -5,10 +5,10 @@ addopts = --verbose --capture=no -rs [annofab] +;endpoint_url = "https://annofab.com" + # Caution : Annofab project may be changed!! # Specify AnnoFab project that has owner role assigned to you. project_id = 58a2a621-7d4b-41e7-927b-cdc570c1114a task_id = sample_423 - -input_data_id = c2a3223b-90db-4416-8c7c-55bf140af1cd diff --git a/tests/data/simple-annotation-v2.zip b/tests/data/simple-annotation-v2.zip deleted file mode 100755 index 8aaf37c1..00000000 Binary files a/tests/data/simple-annotation-v2.zip and /dev/null differ diff --git a/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/1e2931d2-de34-4956-ab75-81f710dc0108 b/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/1e2931d2-de34-4956-ab75-81f710dc0108 deleted file mode 100644 index efe39987..00000000 Binary files a/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/1e2931d2-de34-4956-ab75-81f710dc0108 and /dev/null differ diff --git a/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/762f113a-5e17-4b49-861e-dfbea1dda09d b/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/762f113a-5e17-4b49-861e-dfbea1dda09d deleted file mode 100644 index 0f639f64..00000000 Binary files a/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/762f113a-5e17-4b49-861e-dfbea1dda09d and /dev/null differ diff --git a/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 b/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 deleted file mode 100644 index 80690205..00000000 Binary files a/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 and /dev/null differ diff --git a/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 b/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 deleted file mode 100644 index efe39987..00000000 Binary files a/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 and /dev/null differ diff --git a/tests/data/simple-annotation.zip b/tests/data/simple-annotation.zip index 81d47519..8aaf37c1 100755 Binary files a/tests/data/simple-annotation.zip and b/tests/data/simple-annotation.zip differ diff --git a/tests/data/simple-annotation/sample_0/.__tests__data__lenna.png.json b/tests/data/simple-annotation/sample_0/.__tests__data__lenna.png.json deleted file mode 100644 index b470c162..00000000 --- a/tests/data/simple-annotation/sample_0/.__tests__data__lenna.png.json +++ /dev/null @@ -1 +0,0 @@ -{"project_id":"1186bb00-16e6-4d20-8e24-310322911850","annotation_format_version":"1.2.0","task_id":"sample_0","task_phase":"acceptance","task_phase_stage":1,"task_status":"not_started","input_data_id":"a3281975-e632-47a7-a71f-08013fad5604","input_data_name":"./tests/data/lenna.png","details":[{"label":"climatic","annotation_id":"5ac0d7d5-6738-4c4b-a69a-cd583ff458e1","data":{"_type":"Classification"},"attributes":{"temparature":"20","weather":"sunny"}}],"updated_datetime":"2019-08-22T12:36:14.015+09:00"} \ No newline at end of file diff --git a/tests/data/simple-annotation-v2/sample_0/0733d1e1-ef85-455e-aec0-ff05c499b711.json b/tests/data/simple-annotation/sample_0/0733d1e1-ef85-455e-aec0-ff05c499b711.json similarity index 100% rename from tests/data/simple-annotation-v2/sample_0/0733d1e1-ef85-455e-aec0-ff05c499b711.json rename to tests/data/simple-annotation/sample_0/0733d1e1-ef85-455e-aec0-ff05c499b711.json diff --git a/tests/data/simple-annotation-v2/sample_0/a3281975-e632-47a7-a71f-08013fad5604.json b/tests/data/simple-annotation/sample_0/a3281975-e632-47a7-a71f-08013fad5604.json similarity index 100% rename from tests/data/simple-annotation-v2/sample_0/a3281975-e632-47a7-a71f-08013fad5604.json rename to tests/data/simple-annotation/sample_0/a3281975-e632-47a7-a71f-08013fad5604.json diff --git a/tests/data/simple-annotation/sample_1/.__tests__data__lenna.png.json b/tests/data/simple-annotation/sample_1/.__tests__data__lenna.png.json deleted file mode 100644 index c2b0d8f2..00000000 --- a/tests/data/simple-annotation/sample_1/.__tests__data__lenna.png.json +++ /dev/null @@ -1 +0,0 @@ -{"project_id":"1186bb00-16e6-4d20-8e24-310322911850","annotation_format_version":"1.2.0","task_id":"sample_1","task_phase":"acceptance","task_phase_stage":1,"task_status":"complete","input_data_id":"c6e1c2ec-6c7c-41c6-9639-4244c2ed2839","input_data_name":"./tests/data/lenna.png","details":[{"label":"bird","annotation_id":"9a15fac0-736f-454f-a50d-7da094bc133d","data":{"points":[{"x":15,"y":55},{"x":12,"y":49},{"x":9,"y":43},{"x":16,"y":36},{"x":21,"y":39},{"x":24,"y":53}],"_type":"Points"},"attributes":{}},{"label":"human","annotation_id":"762f113a-5e17-4b49-861e-dfbea1dda09d","data":{"data_uri":"762f113a-5e17-4b49-861e-dfbea1dda09d","_type":"SegmentationV2"},"attributes":{}},{"label":"dog","annotation_id":"1e2931d2-de34-4956-ab75-81f710dc0108","data":{"data_uri":"1e2931d2-de34-4956-ab75-81f710dc0108","_type":"Segmentation"},"attributes":{}},{"label":"eye","annotation_id":"a05019fd-6e23-456b-9971-641a45979d98","data":{"point":{"x":25,"y":18},"_type":"SinglePoint"},"attributes":{}},{"label":"leg","annotation_id":"c9c688d1-6c05-4118-94c7-308185cdb60a","data":{"points":[{"x":22,"y":29},{"x":33,"y":41}],"_type":"Points"},"attributes":{}},{"label":"Cat","annotation_id":"6602c86c-5e22-42b9-b5a4-8a77c7bade01","data":{"left_top":{"x":10,"y":7},"right_bottom":{"x":36,"y":36},"_type":"BoundingBox"},"attributes":{"weight":3,"name":"lena","link-eye":"a05019fd-6e23-456b-9971-641a45979d98","occluded":true,"object id":"6602c86c-5e22-42b9-b5a4-8a77c7bade01","memo":"テスト"}},{"label":"climatic","annotation_id":"5ac0d7d5-6738-4c4b-a69a-cd583ff458e1","data":{"_type":"Classification"},"attributes":{"temparature":"20","weather":"sunny"}}],"updated_datetime":"2019-08-22T14:10:14.758+09:00"} \ No newline at end of file diff --git a/tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json b/tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json rename to tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839.json diff --git a/tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/1e2931d2-de34-4956-ab75-81f710dc0108 b/tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/1e2931d2-de34-4956-ab75-81f710dc0108 similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/1e2931d2-de34-4956-ab75-81f710dc0108 rename to tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/1e2931d2-de34-4956-ab75-81f710dc0108 diff --git a/tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/762f113a-5e17-4b49-861e-dfbea1dda09d b/tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/762f113a-5e17-4b49-861e-dfbea1dda09d similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/762f113a-5e17-4b49-861e-dfbea1dda09d rename to tests/data/simple-annotation/sample_1/c6e1c2ec-6c7c-41c6-9639-4244c2ed2839/762f113a-5e17-4b49-861e-dfbea1dda09d diff --git a/tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json b/tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json rename to tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json diff --git a/tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 b/tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 rename to tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/e2a1fbe3-fa8e-413c-be31-882f12ef62b9 diff --git a/tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 b/tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 similarity index 100% rename from tests/data/simple-annotation-v2/sample_1/.__tests__data__lenna.png/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 rename to tests/data/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b/ee83756f-074d-4aab-8bfc-6ab6e754c2b8 diff --git a/tests/test_api.py b/tests/test_api.py index b533c619..0a4576b1 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -24,47 +24,46 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)) + "/../") inifile = configparser.ConfigParser() inifile.read("./pytest.ini", "UTF-8") -project_id = inifile.get("annofab", "project_id") + +project_id = inifile["annofab"]["project_id"] +task_id = inifile["annofab"]["task_id"] + test_dir = "./tests/data" out_dir = "./tests/out" -service = annofabapi.build_from_netrc() +endpoint_url = inifile["annofab"].get("endpoint_url", None) +if endpoint_url is not None: + service = annofabapi.build(endpoint_url=endpoint_url) +else: + service = annofabapi.build() api = service.api wrapper = service.wrapper test_wrapper = WrapperForTest(api) -my_account_id = api.get_my_account()[0]["account_id"] -organization_name = api.get_organization_of_project(project_id)[0]["organization_name"] - -annofab_user_id = service.api.login_user_id - -task_id = test_wrapper.get_first_task_id(project_id) -input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) - class TestAccount: pass class TestAnnotation: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_wrapper_get_all_annotation_list(self): assert len(wrapper.get_all_annotation_list(project_id, {"query": {"task_id": task_id}})) >= 0 def test_get_annotation(self): - assert type(api.get_annotation(project_id, task_id, input_data_id)[0]) == dict + assert type(api.get_annotation(project_id, task_id, self.input_data_id)[0]) == dict def test_get_editor_annotation(self): - assert type(api.get_editor_annotation(project_id, task_id, input_data_id)[0]) == dict + assert type(api.get_editor_annotation(project_id, task_id, self.input_data_id)[0]) == dict def test_get_annotation_archive(self): content, response = api.get_annotation_archive(project_id) assert response.headers["Location"].startswith("https://") - # v2版の確認 - content, response = api.get_annotation_archive(project_id, query_params={"v2": True}) - assert response.headers["Location"].startswith("https://") - def test_get_archive_full_with_pro_id(self): content, response = api.get_archive_full_with_pro_id(project_id) assert response.headers["Location"].startswith("https://") @@ -106,11 +105,15 @@ def test_get_annotation_specs_relation(self): class TestInput: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_wrapper_get_input_data_list(self): assert type(wrapper.get_all_input_data_list(project_id, {"input_data_name": "foo"})) == list def test_get_input_data(self): - test_input_data = api.get_input_data(project_id, input_data_id)[0] + test_input_data = api.get_input_data(project_id, self.input_data_id)[0] assert type(test_input_data) == dict def test_wrapper_put_input_data_from_file_and_delete_input_data(self): @@ -131,8 +134,12 @@ def test_put_input_data_from_file_and_batch_update_inputs(self): class TestInspection: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_get_inspections(self): - assert len(api.get_inspections(project_id, task_id, input_data_id)[0]) >= 0 + assert len(api.get_inspections(project_id, task_id, self.input_data_id)[0]) >= 0 class TestInstruction: @@ -228,28 +235,36 @@ def test_get_my_member_in_project(self): class TestOrganization: + @classmethod + def setup_class(cls): + cls.organization_name = api.get_organization_of_project(project_id)[0]["organization_name"] + def test_get_organization(self): - assert type(api.get_organization(organization_name)[0]) == dict + assert type(api.get_organization(self.organization_name)[0]) == dict def test_get_organization_activity(self): - assert type(api.get_organization_activity(organization_name)[0]) == dict + assert type(api.get_organization_activity(self.organization_name)[0]) == dict def test_wrapper_get_all_projects_of_organization(self): - assert len(wrapper.get_all_projects_of_organization(organization_name)) > 0 + assert len(wrapper.get_all_projects_of_organization(self.organization_name)) > 0 class TestOrganizationMember: + @classmethod + def setup_class(cls): + cls.organization_name = api.get_organization_of_project(project_id)[0]["organization_name"] + def test_wrapper_get_all_organization_members(self): - assert len(wrapper.get_all_organization_members(organization_name)) > 0 + assert len(wrapper.get_all_organization_members(self.organization_name)) > 0 def test_get_organization_member(self): - organization_member = api.get_organization_member(organization_name, annofab_user_id)[0] + organization_member = api.get_organization_member(self.organization_name, api.login_user_id)[0] assert type(organization_member) == dict def test_update_organization_member_role(self): - organization_member = api.get_organization_member(organization_name, annofab_user_id)[0] + organization_member = api.get_organization_member(self.organization_name, api.login_user_id)[0] request_body = {"role": "owner", "last_updated_datetime": organization_member["updated_datetime"]} - api.update_organization_member_role(organization_name, annofab_user_id, request_body=request_body) + api.update_organization_member_role(self.organization_name, api.login_user_id, request_body=request_body) class TestProject: @@ -287,7 +302,7 @@ def test_wrapper_download_project_inspections_url(self): class TestProjectMember: def test_get_project_member(self): - my_member = api.get_project_member(project_id, annofab_user_id)[0] + my_member = api.get_project_member(project_id, api.login_user_id)[0] assert type(my_member) == dict def test_wrapper_get_all_project_members(self): @@ -342,6 +357,10 @@ def test_graph_marker(self): class Testsupplementary: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_supplementary(self): supplementary_data_id = str(uuid.uuid4()) request_body = {"supplementary_data_number": 1} @@ -349,19 +368,23 @@ def test_supplementary(self): print("") print(f"wrapper.put_supplementary_data_from_file: supplementary_data_id={supplementary_data_id}") content = wrapper.put_supplementary_data_from_file( - project_id, input_data_id, supplementary_data_id, f"{test_dir}/sample.txt", request_body=request_body + project_id, self.input_data_id, supplementary_data_id, f"{test_dir}/sample.txt", request_body=request_body ) assert type(content) == dict - supplementary_data_list = api.get_supplementary_data_list(project_id, input_data_id)[0] + supplementary_data_list = api.get_supplementary_data_list(project_id, self.input_data_id)[0] assert len([e for e in supplementary_data_list if e["supplementary_data_id"] == supplementary_data_id]) == 1 - api.delete_supplementary_data(project_id, input_data_id, supplementary_data_id) - supplementary_data_list = api.get_supplementary_data_list(project_id, input_data_id)[0] + api.delete_supplementary_data(project_id, self.input_data_id, supplementary_data_id) + supplementary_data_list = api.get_supplementary_data_list(project_id, self.input_data_id)[0] assert len([e for e in supplementary_data_list if e["supplementary_data_id"] == supplementary_data_id]) == 0 class TestTask: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_wraper_get_all_tasks(self): assert type(wrapper.get_all_tasks(project_id, query_params={"task_id": "foo"})) == list @@ -369,7 +392,7 @@ def test_wraper_get_all_tasks(self): def test_initiate_tasks_generation_by_csv(self): csv_file_path = f"{test_dir}/tmp/create_task.csv" test_task_id = str(uuid.uuid4()) - create_csv_for_task(csv_file_path, test_task_id, input_data_id) + create_csv_for_task(csv_file_path, test_task_id, self.input_data_id) content = wrapper.initiate_tasks_generation_by_csv(project_id, csv_file_path) assert type(content) == dict @@ -378,7 +401,7 @@ def test_get_task(self): def test_put_task_and_delete_task(self): test_task_id = str(uuid.uuid4()) - request_body = {"input_data_id_list": [input_data_id]} + request_body = {"input_data_id_list": [self.input_data_id]} print("") print(f"put_task: task_id={task_id}") test_task_data = api.put_task(project_id, test_task_id, request_body=request_body)[0] @@ -396,7 +419,7 @@ def test_operate_task(self): request_body = { "status": "not_started", "last_updated_datetime": task["updated_datetime"], - "account_id": my_account_id, + "account_id": api.account_id, } assert type(api.operate_task(project_id, task_id, request_body=request_body)[0]) == dict @@ -405,7 +428,7 @@ def test_get_task_histories(self): def test_batch_update_tasks(self): test_task_id = str(uuid.uuid4()) - request_body = {"input_data_id_list": [input_data_id]} + request_body = {"input_data_id_list": [self.input_data_id]} print("") print(f"put_task: task_id={task_id}") test_task_data = api.put_task(project_id, test_task_id, request_body=request_body)[0] @@ -446,7 +469,7 @@ def test_get_labor_control_worktime(self): wrapper.get_labor_control_worktime(project_id=project_id) def test_get_labor_control_availability(self): - wrapper.get_labor_control_availability(account_id=my_account_id) + wrapper.get_labor_control_availability(account_id=api.account_id) class TestGetObjOrNone: @@ -454,24 +477,29 @@ class TestGetObjOrNone: wrapper.get_xxx_or_none メソッドの確認 """ + @classmethod + def setup_class(cls): + cls.organization_name = api.get_organization_of_project(project_id)[0]["organization_name"] + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_get_input_data_or_none(self): - assert type(wrapper.get_input_data_or_none(project_id, input_data_id)) == dict + assert type(wrapper.get_input_data_or_none(project_id, self.input_data_id)) == dict assert wrapper.get_input_data_or_none(project_id, "not-exists") is None - assert wrapper.get_input_data_or_none("not-exists", input_data_id) is None + assert wrapper.get_input_data_or_none("not-exists", self.input_data_id) is None def test_get_organization_or_none(self): - assert type(wrapper.get_organization_or_none(organization_name)) == dict + assert type(wrapper.get_organization_or_none(self.organization_name)) == dict assert wrapper.get_organization_or_none("not-exists") is None def test_get_organization_member_or_none(self): - assert type(wrapper.get_organization_member_or_none(organization_name, annofab_user_id)) == dict + assert type(wrapper.get_organization_member_or_none(self.organization_name, api.login_user_id)) == dict - assert wrapper.get_organization_member_or_none("not-exists", annofab_user_id) is None + assert wrapper.get_organization_member_or_none("not-exists", api.login_user_id) is None - assert wrapper.get_organization_member_or_none(organization_name, "not-exists") is None + assert wrapper.get_organization_member_or_none(self.organization_name, "not-exists") is None def test_get_project_or_none(self): assert type(wrapper.get_project_or_none(project_id)) == dict @@ -479,11 +507,11 @@ def test_get_project_or_none(self): assert wrapper.get_project_or_none("not-exists") is None def test_get_project_member_or_none(self): - assert type(wrapper.get_project_member_or_none(project_id, annofab_user_id)) == dict + assert type(wrapper.get_project_member_or_none(project_id, api.login_user_id)) == dict assert wrapper.get_project_member_or_none(project_id, "not-exists") is None - assert wrapper.get_project_member_or_none("not-exists", annofab_user_id) is None + assert wrapper.get_project_member_or_none("not-exists", api.login_user_id) is None def test_get_task_or_none(self): assert type(wrapper.get_task_or_none(project_id, task_id)) == dict @@ -505,3 +533,9 @@ def test_request_get_with_cookie_failed(self): url = "https://annofab.com/projects/foo/annotation_specs_histories/foo.json" with pytest.raises(requests.HTTPError): api._request_get_with_cookie(project_id, url) + + +class TestProperty: + def test_account_id(self): + account_id = api.account_id + assert type(account_id) == str and len(account_id) > 0 diff --git a/tests/test_api2.py b/tests/test_api2.py index 2f277ff3..9958d971 100644 --- a/tests/test_api2.py +++ b/tests/test_api2.py @@ -13,19 +13,20 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)) + "/../") inifile = configparser.ConfigParser() inifile.read("./pytest.ini", "UTF-8") -project_id = inifile.get("annofab", "project_id") +project_id = inifile["annofab"]["project_id"] test_dir = "./tests/data" out_dir = "./tests/out" -service = annofabapi.build_from_netrc() -test_wrapper = WrapperForTest(service.api) - -my_account_id = service.api.get_my_account()[0]["account_id"] -organization_name = service.api.get_organization_of_project(project_id)[0]["organization_name"] +endpoint_url = inifile["annofab"].get("endpoint_url", None) +if endpoint_url is not None: + service = annofabapi.build(endpoint_url=endpoint_url) +else: + service = annofabapi.build() -annofab_user_id = service.api.login_user_id +test_wrapper = WrapperForTest(service.api) def test_project(): - assert type(service.api2.get_project_cache_v2(project_id)) + content, _ = service.api2.get_project_cache_v2(project_id) + assert type(content) == dict diff --git a/tests/test_dataclass.py b/tests/test_dataclass.py index 04532905..a7ccd0d7 100644 --- a/tests/test_dataclass.py +++ b/tests/test_dataclass.py @@ -33,24 +33,26 @@ os.chdir(os.path.dirname(os.path.abspath(__file__)) + "/../") inifile = configparser.ConfigParser() inifile.read("./pytest.ini", "UTF-8") -project_id = inifile.get("annofab", "project_id") -task_id = inifile.get("annofab", "task_id") -input_data_id = inifile.get("annofab", "input_data_id") +project_id = inifile["annofab"]["project_id"] +task_id = inifile["annofab"]["task_id"] test_dir = Path("./tests/data") -service = annofabapi.build_from_netrc() +endpoint_url = inifile["annofab"].get("endpoint_url", None) +if endpoint_url is not None: + service = annofabapi.build(endpoint_url=endpoint_url) +else: + service = annofabapi.build() test_wrapper = WrapperForTest(service.api) -my_account_id = service.api.get_my_account()[0]["account_id"] -organization_name = service.api.get_organization_of_project(project_id)[0]["organization_name"] - -annofab_user_id = service.api.login_user_id - class TestAnnotation: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_get_editor_annotation(self): - dict_obj, _ = service.api.get_editor_annotation(project_id, task_id, input_data_id) + dict_obj, _ = service.api.get_editor_annotation(project_id, task_id, self.input_data_id) dataclass_obj = Annotation.from_dict(dict_obj) assert type(dataclass_obj) == Annotation @@ -62,7 +64,7 @@ def test_simple_annotation(self): assert type(single_annotation) == SingleAnnotation def test_full_annotation(self): - dict_simple_annotation, _ = service.api.get_annotation(project_id, task_id, input_data_id) + dict_simple_annotation, _ = service.api.get_annotation(project_id, task_id, self.input_data_id) simple_annotation = SimpleAnnotation.from_dict(dict_simple_annotation) assert type(simple_annotation) == SimpleAnnotation @@ -82,8 +84,12 @@ def test_input_data(self): class TestInspection: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_inspection(self): - inspection_list, _ = service.api.get_inspections(project_id, task_id, input_data_id) + inspection_list, _ = service.api.get_inspections(project_id, task_id, self.input_data_id) inspection = Inspection.from_dict(inspection_list[0]) assert type(inspection) == Inspection @@ -128,20 +134,30 @@ def test_my_account(self): class TestOrganization: + @classmethod + def setup_class(cls): + cls.organization_name = service.api.get_organization_of_project(project_id)[0]["organization_name"] + def test_organization(self): - dict_organization, _ = service.api.get_organization(organization_name) + dict_organization, _ = service.api.get_organization(self.organization_name) organization = Organization.from_dict(dict_organization) assert type(organization) == Organization def test_organization_activity(self): - dict_organization_activity, _ = service.api.get_organization_activity(organization_name) + dict_organization_activity, _ = service.api.get_organization_activity(self.organization_name) organization_activity = OrganizationActivity.from_dict(dict_organization_activity) assert type(organization_activity) == OrganizationActivity class TestOrganizationMember: + @classmethod + def setup_class(cls): + cls.organization_name = service.api.get_organization_of_project(project_id)[0]["organization_name"] + def test_organization_member(self): - dict_organization_member, _ = service.api.get_organization_member(organization_name, annofab_user_id) + dict_organization_member, _ = service.api.get_organization_member( + self.organization_name, service.api.login_user_id + ) organization_member = OrganizationMember.from_dict(dict_organization_member) assert type(organization_member) == OrganizationMember @@ -155,7 +171,7 @@ def test_project(self): class TestProjectMember: def test_project_member(self): - dict_project_member, _ = service.api.get_project_member(project_id, annofab_user_id) + dict_project_member, _ = service.api.get_project_member(project_id, service.api.login_user_id) project_member = ProjectMember.from_dict(dict_project_member) assert type(project_member) == ProjectMember @@ -198,8 +214,12 @@ def test_markers(self): class TestSupplementary: + @classmethod + def setup_class(cls): + cls.input_data_id = test_wrapper.get_first_input_data_id_in_task(project_id, task_id) + def test_supplementary(self): - supplementary_data_list, _ = service.api.get_supplementary_data_list(project_id, input_data_id) + supplementary_data_list, _ = service.api.get_supplementary_data_list(project_id, self.input_data_id) supplementary_data = SupplementaryData.from_dict(supplementary_data_list[0]) assert type(supplementary_data) == SupplementaryData diff --git a/tests/test_local_parser.py b/tests/test_local_parser.py index 51977580..4c16ca45 100644 --- a/tests/test_local_parser.py +++ b/tests/test_local_parser.py @@ -27,7 +27,7 @@ class TestSimpleAnnotationV2: def test_simple_annotation_zip(self): - zip_path = Path(test_dir / "simple-annotation-v2.zip") + zip_path = Path(test_dir / "simple-annotation.zip") iter_parser = annofabapi.parser.lazy_parse_simple_annotation_zip(zip_path) index = 0 @@ -50,7 +50,7 @@ def test_simple_annotation_zip(self): parser.open_outer_file("foo") def test_simple_annotation_dir(self): - dir_path = Path(test_dir / "simple-annotation-v2") + dir_path = Path(test_dir / "simple-annotation") iter_parser = annofabapi.parser.lazy_parse_simple_annotation_dir(dir_path) index = 0 @@ -68,7 +68,7 @@ def test_simple_annotation_dir(self): parser.open_outer_file("foo") def test_lazy_parse_simple_annotation_zip_by_task(self): - zip_path = Path(test_dir / "simple-annotation-v2.zip") + zip_path = Path(test_dir / "simple-annotation.zip") task_parser_list = list(annofabapi.parser.lazy_parse_simple_annotation_zip_by_task(zip_path)) assert len(task_parser_list) == 2 @@ -82,7 +82,7 @@ def test_lazy_parse_simple_annotation_zip_by_task(self): assert len([e for e in parser_list if e.input_data_id == "c86205d1-bdd4-4110-ae46-194e661d622b"]) == 1 def test_lazy_parse_simple_annotation_dir_by_task(self): - zip_path = Path(test_dir / "simple-annotation-v2") + zip_path = Path(test_dir / "simple-annotation") task_parser_list = list(annofabapi.parser.lazy_parse_simple_annotation_dir_by_task(zip_path)) assert len(task_parser_list) == 2 @@ -129,7 +129,7 @@ def test_full_annotation_dir(self): assert index == 4 parser = FullAnnotationDirParser( - Path(f"{test_dir}/simple-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json") + Path(f"{test_dir}/full-annotation/sample_1/c86205d1-bdd4-4110-ae46-194e661d622b.json") ) assert parser.task_id == "sample_1" assert parser.input_data_id == "c86205d1-bdd4-4110-ae46-194e661d622b" diff --git a/tests/test_local_resource.py b/tests/test_local_resource.py index 71969d68..e35b1389 100644 --- a/tests/test_local_resource.py +++ b/tests/test_local_resource.py @@ -5,9 +5,8 @@ import pytest -import annofabapi import annofabapi.exceptions -from annofabapi.resource import build_from_netrc_or_env +from annofabapi.resource import build, build_from_env, build_from_netrc # プロジェクトトップに移動する os.chdir(os.path.dirname(os.path.abspath(__file__)) + "/../") @@ -16,7 +15,7 @@ class TestBuild: def test_build_from_netrc(self): # ".netrc"ファイルが存在すること前提 - assert isinstance(annofabapi.build_from_netrc(), annofabapi.Resource) + assert isinstance(build_from_netrc(), annofabapi.Resource) def test_raise_ValueError(self): with pytest.raises(ValueError): @@ -26,19 +25,23 @@ def test_build_from_env_raise_AnnofabApiException(self): with pytest.raises(annofabapi.exceptions.AnnofabApiException): os.environ.pop("ANNOFAB_USER_ID", None) os.environ.pop("ANNOFAB_PASSWORD", None) - annofabapi.build_from_env() + build_from_env() def test_build_from_env(self): os.environ["ANNOFAB_USER_ID"] = "FOO" os.environ["ANNOFAB_PASSWORD"] = "BAR" - assert isinstance(annofabapi.build_from_env(), annofabapi.Resource) + assert isinstance(build_from_env(), annofabapi.Resource) - def test_build_from_netrc_or_env(self): + def test_build(self): os.environ["ANNOFAB_USER_ID"] = "FOO" os.environ["ANNOFAB_PASSWORD"] = "BAR" - assert isinstance(build_from_netrc_or_env(), annofabapi.Resource) + assert isinstance(build(), annofabapi.Resource) def test_build_with_endpoint(self): - resource = annofabapi.build("test_user", "password", "https://localhost:8080") + user_id = "test_user" + password = "password" + resource = build(user_id, password, "https://localhost:8080") assert resource.api.url_prefix == "https://localhost:8080/api/v1" assert resource.api2.url_prefix == "https://localhost:8080/api/v2" + assert resource.api.login_user_id == user_id + assert resource.api.login_password == password