Azure DevOps Server 2020で「テストケースをREST APIから新規作成し、手順(ステップ)と期待結果まで全部まとめて登録したい」のに、ドキュメントで見つかるのは削除(DELETE)ばかり……という状況は珍しくありません。ポイントは、テストケースが“専用エンティティ”ではなく「Test Case」タイプの作業項目(Work Item)として扱われること。本記事ではWork Item APIを使って、1件のテストケースを作成し、ステップと期待結果まで一括登録する実装手順を具体例つきで解説します。
Azure DevOps Server 2020のテストケースは「Test Case」タイプの作業項目
Azure DevOps Server 2020では、テストケースは「テストケース専用テーブル」や「テストケース専用作成API」で管理されているわけではありません。内部的には、Work Item(作業項目)の種類(Work Item Type)が「Test Case」という位置付けです。
検索すると「Test Case のDELETE(削除)」や「Test Plan関連API」ばかりがヒットして、作成方法が見つからないことがありますが、これは「テストケース作成はWork Item作成として扱う」ためです。ドキュメントがTFS 2017やAzure DevOps Server 2019向けの記載であっても、Azure DevOps Server 2020でも考え方は基本的に同じで、Work Item APIで作成できます。
この構造を踏まえると、やるべきことはシンプルです。
- テストケースを作る=Work Itemを作る(Work Item TypeはTest Case)
- 手順と期待結果を入れる=Work Itemの特定フィールド(Microsoft.VSTS.TCM.Steps)に値を入れる
- テスト計画/スイートへの追加=テスト管理側APIで「関連付け」を作る(作成とは別)
| 目的 | 使うAPI | 考え方 |
|---|---|---|
| テストケース(Test Case)を新規作成 | Work Item API | Work Item TypeをTest Caseにして作業項目を作る |
| ステップと期待結果を登録 | Work Item API | Microsoft.VSTS.TCM.StepsにXML文字列を入れる |
| テスト計画・テストスイートへの紐付け | Test Plan / Test Suite API | 作成したWork Item IDを計画・スイートに追加する |
| 実行結果(Pass/Fail)を扱う | Test Run / Test Result API | 結果はテストケース本体ではなく実行結果側に保存される |
まず押さえるべき前提(URL構造・認証・権限)
URL構造(サーバー/コレクション/プロジェクト)
オンプレミスのAzure DevOps Serverは、環境ごとにURLの見え方が少し異なります。サンプルのURLをコピーしても動かない場合は、「どの部分が可変なのか」を先に整理しておくと迷いません。
| 要素 | 意味 | 例 | 補足 |
|---|---|---|---|
| {server} | Azure DevOps Serverのホスト(ポート含むことあり) | https://devops.example.local:8080 | http/https、ポートは環境依存 |
| {collection} | コレクション名(DefaultCollectionなど) | tfs/DefaultCollection | 構成によりtfs配下になっていることが多い |
| {project} | プロジェクト名 | MyProject | 空白がある場合はURLエンコード(%20)が必要 |
本記事のサンプルは次の形式を前提に書きます。
https://{server}/{collection}/{project}/_apis/...
認証(PAT/Windows統合認証)
REST APIの呼び出し方法は、運用ポリシーによりいくつかあります。よくあるのは次の2パターンです。
- PAT(Personal Access Token)をBasic認証で送る
- 社内AD環境などでWindows統合認証(NTLM/Kerberos)を使う
PATを使う場合は、トークンの権限(スコープ)と有効期限、そして「どのユーザーとして作成されるか」に注意してください。テストケース作成が目的なら、少なくとも作業項目の作成・編集に相当する権限が必要になります。
権限(401/403を早く潰す)
APIの失敗で多いのは次のパターンです。
- 401:認証情報が送れていない/形式が違う/トークンが無効
- 403:認証はできているが、作成・編集の権限がない
まずは同じユーザーでWeb UIからテストケースを作成できるかを確認し、UIで作れるのにAPIだけ403になるなら、PATのスコープや対象プロジェクトの権限設定を疑うのが近道です。
テストケース作成はPOSTではなくPATCH(JSON Patch)
「作成=POST」と思いがちですが、Azure DevOpsのWork Item作成は、JSON PatchをPATCHで送るのが基本です。テストケース作成の代表例は次の通りです。
PATCH https://{server}/{collection}/{project}/_apis/wit/workitems/$Test%20Case?api-version=6.0
Content-Type: application/json-patch+json
- Work Item TypeはURL中で $Test%20Case(スペースは%20)
- ヘッダーのContent-Typeが必須(ここが違うと415になりやすい)
- api-versionはサーバーの互換性で変わるため、まずは動作している既存ツールや環境の例に合わせる
JSON Patchの書き方(op / path / value)
JSON Patchは配列で、操作(op)、対象(path)、値(value)を並べます。作成時はほとんどがaddです。
| op | 意味 | 作成時の使いどころ | 例 |
|---|---|---|---|
| add | 値を追加 | タイトル、説明、Stepsなどを設定 | /fields/System.Title |
| replace | 値を置換 | (作成後)説明やStepsの更新 | /fields/System.Description |
| remove | 値を削除 | (作成後)タグ削除など | /fields/System.Tags |
| add(relations) | リンクを追加 | (作成後)要件やバグとの関連付け | /relations/- |
フィールド指定は基本的に /fields/フィールド参照名 です。表示名と参照名は一致しないことがあるため、参照名を正しく知ることが重要です。
テストケースでよく使うフィールド(必須は環境で変わる)
「必要なフィールド一覧が分からない」という悩みは、プロセスのカスタマイズ(必須項目の追加、ルール設定)が絡むため起きやすいです。まずは頻出フィールドから実装し、400エラーが出たら必須項目を追加する運用が現実的です。
| 参照名 | 内容 | 優先度 | 補足 |
|---|---|---|---|
| System.Title | テストケース名 | 高 | ほぼ必須。最小構成でも必ず入れる |
| System.Description | 説明 | 高 | 目的、前提条件、データ条件を書くと再利用性が上がる |
| Microsoft.VSTS.TCM.Steps | 手順と期待結果 | 高 | XML形式の文字列(後述) |
| System.AreaPath | エリアパス | 中 | 省略しても既定値が入る構成もあるが、必須化されている場合がある |
| System.IterationPath | イテレーションパス | 中 | 同上。運用ルールに合わせて明示すると安定 |
| System.Tags | タグ | 中 | 検索性が上がる(例:Login;Smoke) |
| Microsoft.VSTS.Common.Priority | 優先度 | 低〜中 | 優先度でフィルタしたい運用なら設定 |
参照名・必須項目を調べる(実務で一番堅い方法)
プロセスのカスタマイズがあると「必須」が増えます。作成に失敗したときは、Test Caseのフィールド一覧を取得して確認すると手戻りが減ります。代表的には次のような取得イメージになります。
GET https://{server}/{collection}/{project}/_apis/wit/workitemtypes/Test%20Case/fields?api-version=6.0
ここで取得できるフィールドの参照名をもとに、JSON Patchに不足分を追加します。
ステップと期待結果の入れ方(Microsoft.VSTS.TCM.Steps)
テストケースを“テストケースらしく”する要素が、ステップ(手順)と期待結果です。これを保存するフィールドが Microsoft.VSTS.TCM.Steps で、形式はXML文字列です。
XMLの基本構造(ActionとExpectedが2つのparameterizedString)
最小構成は次の形です。1つの<step>に、操作内容と期待結果がペアで入ります。
<steps id="0" last="2">
<step id="1" type="ActionStep">
<parameterizedString isformatted="true">ユーザー名を入力する</parameterizedString>
<parameterizedString isformatted="true">ユーザー名が受け付けられる</parameterizedString>
</step>
<step id="2" type="ActionStep">
<parameterizedString isformatted="true">パスワードを入力してログインボタンを押す</parameterizedString>
<parameterizedString isformatted="true">ログインに成功し、ホーム画面が表示される</parameterizedString>
</step>
</steps>
| 要素 | 役割 | 実装上の注意 |
|---|---|---|
| <steps id=”0″ last=”N”> | 全ステップのルート | lastは最後のstep idに合わせると安全(例:2ステップなら2) |
| <step id=”n” type=”ActionStep”> | 1ステップ | idは重複しない連番にする |
| 1つ目のparameterizedString | 操作内容 | 「誰が何をするか」を実行できる粒度で書く |
| 2つ目のparameterizedString | 期待結果 | 合否判定できる観点で具体化する(表示、遷移、メッセージ等) |
| isformatted=”true” | 書式付き扱い | 必要に応じて改行や箇条書きを含められる運用もある |
エスケープの考え方(XMLとして正しい→JSON文字列として正しい)
Stepsは「XML文字列をJSONに入れる」ので、壊れるポイントが2段階あります。
- XMLとして妥当か(& や < が含まれると要エスケープ)
- JSON文字列として妥当か(ダブルクォートや改行の扱い)
実務では、ステップを配列で持ち、最後にXMLを組み立て、JSON化(ConvertTo-Jsonなど)に任せると安定します。
実際に作成するJSON Patch例(タイトル+説明+Steps)
次のJSON Patchを送ると、「ステップと期待結果を持ったテストケース」を新規作成できます。
[
{
"op": "add",
"path": "/fields/System.Title",
"value": "ログイン機能のテストケース"
},
{
"op": "add",
"path": "/fields/System.Description",
"value": "ログイン画面の基本動作を確認するテスト(前提:有効なユーザーが存在する)"
},
{
"op": "add",
"path": "/fields/Microsoft.VSTS.TCM.Steps",
"value": "<steps id=\\"0\\" last=\\"2\\">...</steps>"
}
]
説明(Description)に「前提条件」や「準備データ」を書く運用にすると、テスト実行時の手戻りが減ります。テストケース生成を自動化するほど、この差が効いてきます。
curlで作成する(API疎通の最短ルート)
最初はcurlで疎通確認すると、認証・URL・Content-Typeの問題を切り分けやすくなります。以下はPATをBasic認証で渡す例です(PATの管理は必ず社内ルールに従ってください)。
curl -X PATCH \
-H "Content-Type: application/json-patch+json" \
-H "Authorization: Basic {BASE64(:PAT)}" \
"https://{server}/{collection}/{project}/_apis/wit/workitems/$Test%20Case?api-version=6.0" \
-d '[
{"op":"add","path":"/fields/System.Title","value":"ログイン機能のテストケース"},
{"op":"add","path":"/fields/System.Description","value":"ログイン画面の基本動作を確認するテスト"},
{"op":"add","path":"/fields/Microsoft.VSTS.TCM.Steps","value":"<steps id=\\"0\\" last=\\"2\\">...</steps>"}
]'
JSON Patchは別ファイルに分け、-d @body.jsonにすると引用符や改行の事故が減ります。
PowerShellで作成する(ステップ生成まで含めて実用的に)
PowerShellで社内ツール化するなら、「ステップ配列→Steps XML生成→Work Item作成」という形にするのがおすすめです。サンプルとして、ステップ配列からXMLを組み立てる骨格を示します。
$server = "https://devops.example.local:8080"
$collection = "tfs/DefaultCollection"
$project = "MyProject"
$apiVersion = "6.0"
$pat = "xxxxx"
$uri = "$server/$collection/$project/_apis/wit/workitems/`$Test%20Case?api-version=$apiVersion"
# Basic認証ヘッダー(ユーザー名は空、:PATをBase64化)
$token = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
$headers = @{
"Authorization" = "Basic $token"
"Content-Type" = "application/json-patch+json"
}
# 入力(ステップを配列で管理)
$steps = @(
@{ action = "ユーザー名を入力する"; expected = "ユーザー名が受け付けられる" },
@{ action = "パスワードを入力してログインボタンを押す"; expected = "ログインに成功し、ホーム画面が表示される" }
)
function New-StepsXml([object[]]$steps) {
$sb = New-Object System.Text.StringBuilder
[void]$sb.Append("<steps id=\\"0\\" last=\\"$($steps.Count)\\">")
for ($i = 0; $i -lt $steps.Count; $i++) {
$id = $i + 1
# XMLとして壊れないようにエスケープ(< や & など)
$a = [System.Security.SecurityElement]::Escape([string]$steps[$i].action)
$e = [System.Security.SecurityElement]::Escape([string]$steps[$i].expected)
[void]$sb.Append("<step id=\\"$id\\" type=\\"ActionStep\\">")
[void]$sb.Append("<parameterizedString isformatted=\\"true\\">$a</parameterizedString>")
[void]$sb.Append("<parameterizedString isformatted=\\"true\\">$e</parameterizedString>")
[void]$sb.Append("</step>")
}
[void]$sb.Append("</steps>")
return $sb.ToString()
}
$stepsXml = (New-StepsXml $steps)
$body = @(
@{ op = "add"; path = "/fields/System.Title"; value = "ログイン機能のテストケース" },
@{ op = "add"; path = "/fields/System.Description"; value = "ログイン画面の基本動作を確認するテスト" },
@{ op = "add"; path = "/fields/Microsoft.VSTS.TCM.Steps"; value = $stepsXml }
) | ConvertTo-Json -Depth 10
Invoke-RestMethod -Method Patch -Uri $uri -Headers $headers -Body $body
上記は「XMLとしての妥当性」を先に担保してからJSON化しています。JSONのエスケープ(ダブルクォートや改行)は ConvertTo-Json が担ってくれるため、手作業の文字列連結を減らせます。
作成後に確認する(GETで取り出して差分を潰す)
テストケース生成を自動化するときは、作成→取得→UI確認のループを早めに作っておくと安定します。作成レスポンスからWork Item IDが取れるので、次のようなGETで確認できます。
GET https://{server}/{collection}/{project}/_apis/wit/workitems/{id}?api-version=6.0
返ってきたJSONの中に fields があり、その中に Microsoft.VSTS.TCM.Steps が入っていれば、登録自体は成功しています。UIに表示されない場合は、Steps XMLの構造(id/last、step要素の並び、エスケープ)を疑ってください。
既存テストケースの更新も同じ考え方(PATCHでreplace)
「最初はタイトルと説明だけ作り、後からステップを入れる」運用もよくあります。その場合は、作成用のURL($Test%20Case)ではなく、作成済みのWork Item IDを指定してPATCHします。
PATCH https://{server}/{collection}/{project}/_apis/wit/workitems/{id}?api-version=6.0
更新はaddではなくreplaceを使うことが増えます(もちろんフィールドが未設定ならaddでも成立します)。
「結果(Pass/Fail)」はテストケースではなく実行結果側にある
質問文で「results(結果)も含めたい」と表現されることがありますが、ここは整理しておくと設計ミスを防げます。
| 区分 | 何を持つか | どこに保存されるか |
|---|---|---|
| テストケース(Test Case) | 手順、期待結果、説明、分類情報 | Work Item(Test Caseタイプ) |
| テスト実行(Test Run) | いつ、誰が、どの範囲を実行したか | テスト実行エンティティ側 |
| テスト結果(Test Result) | Pass/Fail、ログ、実行時の添付等 | テスト結果エンティティ側 |
つまり、テストケース作成時に埋めるべき「result」は、ステップに付随する期待結果(Expected Result)のこと、と考えるのが自然です。
テスト計画・テストスイートへの関連付け(役割分担を意識する)
Work Item APIでテストケースを作っても、テスト計画(Test Plan)やテストスイート(Test Suite)に自動的に配置されるわけではありません。これは「作業項目の作成」と「テスト計画の構成管理」が別機能だからです。
実務でのおすすめフローは次の通りです。
- Work Item APIでTest Caseを作成し、Work Item IDを得る
- 必要ならTest Plan / Test Suite APIで、そのIDを特定のスイートに追加する
| 処理 | 必要な情報 | 失敗しやすい点 | 対策 |
|---|---|---|---|
| Test Case作成 | タイトル、説明、Steps XML | Content-Type違い、必須フィールド不足 | JSON Patch+必須フィールド確認 |
| スイートに追加 | Plan ID、Suite ID、Work Item ID | 計画IDの取り違え、権限不足 | UIで同操作できる権限を確認 |
テスト計画/スイート側のAPIは環境やバージョンでapi-versionが変わることがあります。まずは「対象のPlan/Suiteにテストケースを追加できるエンドポイント」をドキュメントで確認し、あなたのAzure DevOps Server 2020のAPIバージョンに合わせて呼び出してください。
よくあるエラーと原因(チェックリスト)
| HTTP/症状 | ありがちな原因 | 見るべきポイント | 対処 |
|---|---|---|---|
| 415 Unsupported Media Type | Content-Typeが違う | application/json-patch+json | ヘッダーを修正 |
| 401 Unauthorized | 認証ヘッダー不備/PAT無効 | Authorizationヘッダー、PAT期限 | トークン再発行、形式見直し |
| 403 Forbidden | 権限不足 | プロジェクト権限、グループ | UI操作できる権限に合わせる |
| 400 Bad Request(フィールド) | 必須フィールド未指定/参照名ミス | Test Caseのフィールド一覧 | 参照名と必須を確認して追加 |
| 400 Bad Request(Steps) | XML構造が不正/エスケープ不足 | XMLとして妥当か | XML生成を関数化し、文字列連結を減らす |
| UIにステップが出ない | last/id不整合、要素不足 | steps/stepのid、last | 連番とlastを整える |
運用を壊さないコツ(自動生成を長く回すために)
- ステップは配列で管理し、Steps XMLの生成は専用関数で一元化(変更点を最小化)
- 必須フィールドはAPIで取得して検出(プロセス変更に追随しやすい)
- 作成結果をGETで取り出し、fieldsの差分をログに残す(不具合の再現が容易)
- テスト計画への紐付けは別処理に分離(リトライ・再実行がしやすい)
Azure DevOps Server 2020で「APIからテストケースを作成し、ステップと期待結果までまとめて登録する」最短ルートは、Work Item APIでTest Caseを作り、Microsoft.VSTS.TCM.StepsにXML文字列を設定することです。ここまでできれば、あとは運用に合わせてタグ、Area/Iteration、関連リンクなどを追加して、より検索しやすく、使い回しやすいテスト資産へ育てられます。

コメント