Skip to main content
Glama
test_esg_api.py11 kB
"""E2E tests for ESG-related APIs.""" import pytest from utils.api_client import TWSEAPIClient from utils.formatters import has_meaningful_data class TestAnticompetitiveLitigationAPI: """反競爭行為法律訴訟 API 測試.""" ENDPOINT = "/opendata/t187ap46_L_20" EXPECTED_FIELDS = [ "出表日期", "報告年度", "公司代號", "公司名稱", "因與反競爭行為條例相關的法律訴訟而造成的金錢損失總額(仟元)" ] def test_response_schema_matches_expected(self): """測試回應 schema 符合預期.""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 取第一筆資料檢查欄位 first_item = data[0] assert isinstance(first_item, dict), "每筆資料應該是 dict" # 檢查所有必要欄位都存在 for field in self.EXPECTED_FIELDS: assert field in first_item, f"欄位 '{field}' 應該存在於回應中" def test_company_code_format(self): """測試公司代號格式正確.""" data = TWSEAPIClient.get_data(self.ENDPOINT) for item in data[:10]: # 檢查前 10 筆 code = item.get("公司代號") assert code is not None, "公司代號不應為 None" assert isinstance(code, str), "公司代號應該是字串" assert code.isdigit(), f"公司代號應該是數字: {code}" assert len(code) == 4, f"公司代號應該是 4 碼: {code}" def test_loss_amount_format(self): """測試損失金額格式正確.""" data = TWSEAPIClient.get_data(self.ENDPOINT) for item in data[:10]: loss = item.get("因與反競爭行為條例相關的法律訴訟而造成的金錢損失總額(仟元)") assert loss is not None, "損失金額欄位不應為 None" # 應該是數字字串或 "0.000" 或 "N/A" assert isinstance(loss, str) or isinstance(loss, (int, float)), \ f"損失金額格式不正確: {loss}" def test_get_company_data_by_code(self, sample_stock_code): """測試依公司代號查詢資料.""" data = TWSEAPIClient.get_company_data(self.ENDPOINT, sample_stock_code) if data: assert data.get("公司代號") == sample_stock_code, \ f"查詢結果應該是指定的公司代號 {sample_stock_code}" def test_filter_non_zero_losses(self): """測試過濾非零損失的邏輯.""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 使用 has_meaningful_data helper 函數 filtered_data = [ item for item in data if isinstance(item, dict) and has_meaningful_data(item, "因與反競爭行為條例相關的法律訴訟而造成的金錢損失總額(仟元)") ] # 檢查過濾後的資料都不是零 for item in filtered_data: loss = item.get("因與反競爭行為條例相關的法律訴訟而造成的金錢損失總額(仟元)") assert loss not in ["0.000", "0", "N/A", "", None], \ f"過濾後不應包含零值或 N/A: {loss}" def test_known_company_with_loss(self, sample_stock_code_with_data): """測試已知有損失的公司(大成 1210).""" data = TWSEAPIClient.get_company_data(self.ENDPOINT, sample_stock_code_with_data) if data: loss = data.get("因與反競爭行為條例相關的法律訴訟而造成的金錢損失總額(仟元)") # 這個測試可能會因為實際資料變化而失敗,這正是我們想要的! # 如果失敗,代表證交所的資料已更新 assert loss not in ["0.000", "0", "N/A", "", None], \ f"大成(1210)應該有訴訟損失資料,但得到: {loss}" class TestInclusiveFinanceAPI: """普惠金融 API 測試.""" ENDPOINT = "/opendata/t187ap46_L_17" EXPECTED_FIELDS = [ "出表日期", "報告年度", "公司代號", "公司名稱", "對促進小型企業及社區發展的貸放件數(件)", "對促進小型企業及社區發展的貸放餘額(仟元)", "對缺少銀行服務之弱勢族群提供金融教育之參與人數(人)" ] def test_response_schema_matches_expected(self): """測試回應 schema 符合預期.""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 取第一筆資料檢查欄位 first_item = data[0] assert isinstance(first_item, dict), "每筆資料應該是 dict" # 檢查所有必要欄位都存在 for field in self.EXPECTED_FIELDS: assert field in first_item, f"欄位 '{field}' 應該存在於回應中" def test_company_code_format(self): """測試公司代號格式正確.""" data = TWSEAPIClient.get_data(self.ENDPOINT) for item in data[:10]: # 檢查前 10 筆 code = item.get("公司代號") assert code is not None, "公司代號不應為 None" assert isinstance(code, str), "公司代號應該是字串" assert code.isdigit(), f"公司代號應該是數字: {code}" assert len(code) == 4, f"公司代號應該是 4 碼: {code}" def test_get_company_data_by_code(self, sample_stock_code): """測試依公司代號查詢資料.""" data = TWSEAPIClient.get_company_data(self.ENDPOINT, sample_stock_code) if data: assert data.get("公司代號") == sample_stock_code, \ f"查詢結果應該是指定的公司代號 {sample_stock_code}" def test_filter_meaningful_data(self): """測試過濾有意義資料的邏輯(任一欄位非零即保留).""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 使用 has_meaningful_data helper 函數 filtered_data = [ item for item in data if isinstance(item, dict) and has_meaningful_data(item, [ "對促進小型企業及社區發展的貸放件數(件)", "對促進小型企業及社區發展的貸放餘額(仟元)", "對缺少銀行服務之弱勢族群提供金融教育之參與人數(人)" ]) ] # 檢查過濾後的資料至少有一個欄位不是零或 N/A for item in filtered_data: loan_count = item.get("對促進小型企業及社區發展的貸放件數(件)") loan_amount = item.get("對促進小型企業及社區發展的貸放餘額(仟元)") education_count = item.get("對缺少銀行服務之弱勢族群提供金融教育之參與人數(人)") # 至少一個欄位應該有意義的數據 has_data = ( loan_count not in ["0", "N/A", "", None] or loan_amount not in ["0.000", "0", "N/A", "", None] or education_count not in ["0", "N/A", "", None] ) assert has_data, \ f"過濾後的資料應該至少有一個欄位有意義: 貸放件數={loan_count}, 貸放餘額={loan_amount}, 教育人數={education_count}" class TestCommunityRelationsAPI: """社區關係 API 測試.""" ENDPOINT = "/opendata/t187ap46_L_15" EXPECTED_FIELDS = [ "出表日期", "報告年度", "公司代號", "公司名稱", "在人口密集地區的煉油廠數量(座)" ] def test_response_schema_matches_expected(self): """測試回應 schema 符合預期.""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 取第一筆資料檢查欄位 first_item = data[0] assert isinstance(first_item, dict), "每筆資料應該是 dict" # 檢查所有必要欄位都存在 for field in self.EXPECTED_FIELDS: assert field in first_item, f"欄位 '{field}' 應該存在於回應中" def test_company_code_format(self): """測試公司代號格式正確.""" data = TWSEAPIClient.get_data(self.ENDPOINT) for item in data[:10]: # 檢查前 10 筆 code = item.get("公司代號") assert code is not None, "公司代號不應為 None" assert isinstance(code, str), "公司代號應該是字串" assert code.isdigit(), f"公司代號應該是數字: {code}" assert len(code) == 4, f"公司代號應該是 4 碼: {code}" def test_refinery_count_format(self): """測試煉油廠數量格式正確.""" data = TWSEAPIClient.get_data(self.ENDPOINT) for item in data[:10]: refinery_count = item.get("在人口密集地區的煉油廠數量(座)") assert refinery_count is not None, "煉油廠數量欄位不應為 None" # 應該是數字字串或 "0" 或 "N/A" assert isinstance(refinery_count, str) or isinstance(refinery_count, (int, float)), \ f"煉油廠數量格式不正確: {refinery_count}" def test_get_company_data_by_code(self, sample_stock_code): """測試依公司代號查詢資料.""" data = TWSEAPIClient.get_company_data(self.ENDPOINT, sample_stock_code) if data: assert data.get("公司代號") == sample_stock_code, \ f"查詢結果應該是指定的公司代號 {sample_stock_code}" def test_filter_non_zero_refineries(self): """測試過濾非零煉油廠的邏輯.""" data = TWSEAPIClient.get_data(self.ENDPOINT) # 使用 has_meaningful_data helper 函數 filtered_data = [ item for item in data if isinstance(item, dict) and has_meaningful_data(item, "在人口密集地區的煉油廠數量(座)") ] # 檢查過濾後的資料都不是零或 N/A for item in filtered_data: refinery_count = item.get("在人口密集地區的煉油廠數量(座)") assert refinery_count not in ["0", "N/A", "", None], \ f"過濾後不應包含零值或 N/A: {refinery_count}" class TestOtherESGAPIs: """其他 ESG API 測試.""" @pytest.mark.parametrize("endpoint", [ "/opendata/t187ap46_L_9", "/opendata/t187ap46_L_8", "/opendata/t187ap46_L_19", "/opendata/t187ap46_L_13", "/opendata/t187ap46_L_16", "/opendata/t187ap46_L_17", "/opendata/t187ap46_L_20", "/opendata/t187ap46_L_15", ]) def test_esg_apis_have_company_code_field(self, endpoint): """測試所有 ESG API 都有公司代號欄位.""" data = TWSEAPIClient.get_data(endpoint) first_item = data[0] assert "公司代號" in first_item, f"{endpoint} 應該包含公司代號欄位"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/twjackysu/TWSEMCPServer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server