Jira测试计划关联测试用例状态更新遇401认证错误求助
Jira测试用例状态修改401错误排查与解决
我需要将Jira测试计划RO-6666中关联到测试执行RO-6665的10个测试用例状态从'TODO'改为'PASS',但执行代码时出现「Failed to retrieve issue details. Status code 401」错误,已核对令牌与权限仍未解决,原代码如下:
import os from jira import JIRA import requests import json # Define your Jira server URL, username, and API token JIRA_SERVER = 'example tokens' JIRA_USER = 'example tokens' JIRA_API_TOKEN = 'example tokens' # Define the Jira issue key for the test plan and execution test_plan_key = 'RO-6666' execution_key = 'RO-6665' # Define the new status to set (e.g., 'PASS') new_status = 'PASS' # Set the Jira API endpoints for issue retrieval and transition issue_url = f"{JIRA_SERVER}/rest/api/2/issue/{execution_key}" transitions_url = f"{issue_url}/transitions" # Define Jira options with headers for authentication and content type jira_options = { 'server': JIRA_SERVER, 'headers': { 'Content-Type': 'application/json' } } # Authenticate using basic auth (username and API token) auth = (JIRA_USER, JIRA_API_TOKEN) # Step 1: Get the issue details response = requests.get(issue_url, headers=jira_options['headers'], auth=auth) if response.status_code != 200: print(f"Failed to retrieve issue details. Status code: {response.status_code}") exit() issue_data = response.json() current_status = issue_data["fields"]["status"]["name"] # Check if the current status is 'TODO' if current_status != 'TODO': print(f"Test execution {execution_key} is not in 'TODO' status. Current status: {current_status}") else: # Step 2: Get available transitions for the issue response = requests.get(transitions_url, headers=jira_options['headers'], auth=auth) if response.status_code != 200: print(f"Failed to retrieve available transitions. Status code: {response.status_code}") exit() transitions_data = response.json() # Find the transition ID for the 'PASS' status for transition in transitions_data["transitions"]: if transition["to"]["name"] == new_status: transition_id = transition["id"] break else: print(f"Transition to '{new_status}' status not found.") exit() # Step 3: Perform the transition to update the status transition_data = {"transition": {"id": transition_id}} response = requests.post(transitions_url, headers=jira_options['headers'], json=transition_data, auth=auth) if response.status_code == 204: print(f"Test execution {execution_key} status updated to '{new_status}'.") else: print(f"Failed to update status. Status code: {response.status_code}")
问题分析与修复方案
核心问题点
- 认证方式错误:Jira Cloud的基础认证要求将
邮箱:API令牌进行Base64编码后放在请求头,原代码直接传入元组的方式不生效。 - 逻辑偏差:原代码试图修改测试执行本身的状态,而非其中关联的测试用例。测试用例是独立的Issue,需要单独处理。
- URL配置不规范:示例URL未替换为实际有效地址,导致请求失败。
修正后的完整代码
import requests import json import base64 # 替换为你的实际Jira配置 JIRA_SERVER = 'https://your-domain.atlassian.net' JIRA_EMAIL = 'your-work-email@example.com' JIRA_API_TOKEN = 'your-generated-api-token' # 目标测试计划和执行Key test_plan_key = 'RO-6666' execution_key = 'RO-6665' target_status = 'PASS' # 生成符合要求的认证头 auth_str = f"{JIRA_EMAIL}:{JIRA_API_TOKEN}" auth_base64 = base64.b64encode(auth_str.encode('utf-8')).decode('utf-8') headers = { 'Content-Type': 'application/json', 'Authorization': f'Basic {auth_base64}' } def fetch_test_execution_cases(exec_key): """获取测试执行关联的所有测试用例""" api_url = f"{JIRA_SERVER}/rest/raven/1.0/api/testexec/{exec_key}/testcases" resp = requests.get(api_url, headers=headers) if resp.status_code != 200: print(f"获取测试用例列表失败,状态码: {resp.status_code}") return [] return resp.json() def get_status_transition_id(issue_key, target_name): """获取Issue到目标状态的转换ID""" api_url = f"{JIRA_SERVER}/rest/api/2/issue/{issue_key}/transitions" resp = requests.get(api_url, headers=headers) if resp.status_code != 200: print(f"获取状态转换列表失败,状态码: {resp.status_code}") return None for transition in resp.json().get('transitions', []): if transition['to']['name'] == target_name: return transition['id'] print(f"未找到到'{target_name}'的状态转换") return None def update_case_status(issue_key, transition_id): """更新单个测试用例的状态""" api_url = f"{JIRA_SERVER}/rest/api/2/issue/{issue_key}/transitions" payload = {"transition": {"id": transition_id}} resp = requests.post(api_url, headers=headers, json=payload) if resp.status_code == 204: print(f"测试用例{issue_key}状态已更新为{target_status}") else: print(f"更新测试用例{issue_key}失败,状态码: {resp.status_code}") # 执行流程 test_cases = fetch_test_execution_cases(execution_key) if not test_cases: print("未找到与测试执行关联的测试用例") exit() for case in test_cases: case_key = case['key'] # 可选:检查当前状态是否为TODO case_resp = requests.get(f"{JIRA_SERVER}/rest/api/2/issue/{case_key}", headers=headers) if case_resp.status_code == 200: current_status = case_resp.json()['fields']['status']['name'] if current_status != 'TODO': print(f"测试用例{case_key}当前状态为{current_status},跳过更新") continue # 获取转换ID并更新状态 transition_id = get_status_transition_id(case_key, target_status) if transition_id: update_case_status(case_key, transition_id)
关键说明
- 认证修正:使用Base64编码邮箱和API令牌,完全符合Jira Cloud的认证规范。
- 测试用例获取:通过Xray插件的API获取测试执行关联的测试用例(Jira测试管理通常依赖Xray)。
- 逐个处理:遍历每个测试用例,检查状态后执行状态转换,确保只修改目标用例。
内容的提问来源于stack exchange,提问作者blackcat
相关产品推荐
相关产品推荐

