🛵

Zephyrのテストサイクルから特定のフォルダ配下のテストケースをまとめて選択・除外する機能をChrome拡張に追加してみた

に公開
2026/01/10

こんにちは。ダイの大冒険エンジョイ勢のbun913と申します。

私は以前Zephyrというテストマネジメントツールをより便利に使うためのChrome拡張機能を公開していました。

https://chromewebstore.google.com/detail/zephyr-ui-extension/fimhkcinaljciihkgojjmehhnonopfcm

以前の記事はこちらです。

https://zenn.dev/bun913/articles/458e6e5fe421f6

私も改善要望などをお出ししていますが、すぐに改善いただくことは現実的に難しい問題をその間だけでも便利に周りの方に使っていただけるように機能追加をする目的でこれを作成・メンテナンスしています。(もし対応いただけたらその機能は削除をしていこうと考えています)

最初に公開した機能は2つですが、今回実は2回目のアップデートとして、私の周りの人が待望していた機能を追加してみました。

早速デモ

主にZephyrユーザーの方に向けた説明になっておりますが、後ほど背景などはご説明します。

Test Cycle に登録されているテストケースを 特定のフォルダ配下のケースだけまとめて選択して除外したり、情報を変更したい と思ったことはありませんか?

こちらの拡張(v0.3.0)を導入すると

  • 各テストケースの名前の下にフォルダのパスが表示される
  • また Select by folder というテキストボックスにフォルダパスを入れると、前方一致で特定のフォルダ配下のテストケースをまとめて 40件まで 一括で選択できる

以下は app1/ というフォルダ配下のテストケースを一気に選択しています。このフォルダはネストしていても対応できるため app1/general_user や app1/permission/admin といったサブフォルダ配下のテストケースもまとめて選択できます。

filter_by_path

機能作成の背景

Zephyrには Test Cycle という形で複数のテストケースをまとめて、実行結果を管理できるようなリソースがあります。 Test Cycle に登録されたテストケースの情報を一括で変更したり、まとめて削除(除外)できて便利です。

ですが、(少なくとも私は)2点ほどつらさを感じています。

  • 本来はテストケースはフォルダというリソースで構造化して管理できるのですが、この画面にはフォルダの情報が表示されていない
    • そのため、たとえば「これらのテストケースは今回実施しなくてよかったな」や「まとめて情報を変更したいな」と思った時に狙ったテストケース群を選択できません
  • 変更したいケースを一括で選択できるのですが、50件より多いリソースを一括選択できたにもかかわらず、まとめて削除といった使い方ができない
    • 51件以上を選択した場合、自分で50件以下になるまでチェックを外していく必要があるようです

そこでこの拡張機能では以下2点に対応しました。

  • まず以下のようにシンプルにテストケースのNameの下に所属するフォルダのパスを表示しました

show_folder

  • 次に以下のようなテストケース一括選択のためのテキストボックスとボタンを用意しました

filter_input

あとは上でご紹介したデモgifのとおり、特定のフォルダ配下のテストケースをまとめて選択できるようにしてみました。もちろんこのあと Delete ボタンで一括で Test Cycle からテストケースをまとめて除外することもできます。

filter_by_path

機能の仕組み

まずは、フォルダの情報を各テストケースの行に追加していきます。

/**
 * Add folder path to a grid row (append to Name cell)
 */
function addFolderPathToRow(
	row: HTMLElement,
	folderPathMap: Map<number, string>,
	testRunItemsMap: Map<number, number | null>,
): void {
	// Check if already processed
	if (row.querySelector(".zephyr-extension-folder-path")) {
		return;
	}

	// Get test run item ID from data-row-id attribute
	const dataRowId = row.getAttribute("data-row-id");
	if (!dataRowId) {
		return;
	}

	const testRunItemId = Number.parseInt(dataRowId, 10);
	const folderId = testRunItemsMap.get(testRunItemId);

	// Get folder path
	if (!folderId || !folderPathMap.has(folderId)) {
		return;
	}
	const folderPath = folderPathMap.get(folderId) || "";

	// Find the name cell
	const nameCell = row.querySelector('td[data-cell-id="name"]');
	if (!nameCell) {
		return;
	}

	// Create folder path label (on new line)
	const folderPathLabel = document.createElement("span");
	folderPathLabel.className = "zephyr-extension-folder-path";
	folderPathLabel.setAttribute("data-folder-path", folderPath);
	folderPathLabel.style.cssText = `
		display: flex;
		align-items: center;
		gap: 4px;
		font-size: 11px;
		color: #888;
		margin-top: 2px;
	`;
	folderPathLabel.title = folderPath; // Full path on hover

	// Add extension icon
	const icon = document.createElement("img");
	icon.src = chrome.runtime.getURL("icon.png");
	icon.style.cssText = `
		width: 12px;
		height: 12px;
		flex-shrink: 0;
	`;

	const text = document.createElement("span");
	text.textContent = folderPath;

	folderPathLabel.appendChild(icon);
	folderPathLabel.appendChild(text);

	// Append to name cell
	nameCell.appendChild(folderPathLabel);
}

なんとも泥臭いですが、既存のコードに手を加えることはできないため、なんとか既存のページに後付けで機能を付与しています。

同様にボタンなども追加しています。

/**
 * Add filter UI (input + button)
 */
function addFilterUI(): void {
	// Check if already added
	if (document.getElementById("zephyr-extension-folder-filter")) {
		return;
	}

	// Find the grid header using data-column-id attribute
	const headerColumn = document.querySelector("[data-column-id]");
	if (!headerColumn || !headerColumn.parentElement) {
		logger.debug("Grid header not found for filter UI");
		return;
	}
	const headerContainer = headerColumn.parentElement;

	// Create filter container
	const filterContainer = document.createElement("div");
	filterContainer.id = "zephyr-extension-folder-filter";
	filterContainer.style.cssText = `
		display: flex;
		align-items: center;
		gap: 8px;
		padding: 8px 0;
	`;

	// Add extension icon
	const icon = document.createElement("img");
	icon.src = chrome.runtime.getURL("icon.png");
	icon.style.cssText = `
		width: 16px;
		height: 16px;
	`;

	// Create label
	const label = document.createElement("span");
	label.textContent = "Select by folder:";
	label.style.cssText = `
		font-size: 12px;
		font-weight: 500;
		color: #333;
	`;

	// Create input
	const input = document.createElement("input");
	input.type = "text";
	input.id = "zephyr-extension-folder-filter-input";
	input.placeholder = "e.g. app1/general_user/login";
	input.style.cssText = `
		padding: 6px 12px;
		border: 1px solid #ddd;
		border-radius: 3px;
		font-size: 12px;
		width: 300px;
	`;

	// Create button
	const button = document.createElement("button");
	button.textContent = "Select Matching (max 40)";
	button.style.cssText = `
		padding: 6px 12px;
		background-color: #0052cc;
		color: white;
		border: none;
		border-radius: 3px;
		font-size: 12px;
		cursor: pointer;
	`;
	button.addEventListener("click", handleFilterClick);
	button.addEventListener("mouseenter", () => {
		button.style.backgroundColor = "#0065ff";
	});
	button.addEventListener("mouseleave", () => {
		button.style.backgroundColor = "#0052cc";
	});

	filterContainer.appendChild(icon);
	filterContainer.appendChild(label);
	filterContainer.appendChild(input);
	filterContainer.appendChild(button);

	// Insert before the header container
	headerContainer.insertAdjacentElement("beforebegin", filterContainer);
	logger.debug("Filter UI added");
}

あとはご想像の通りですが、フォルダパスをテストケースに付与した際に持たせたフォルダパスの情報を元に入力されたフォルダパスと前方一致するテストケースのチェックボックスを有効にする方法をとっています。

また、地味に40件までを一気に選択することにして、後で手動で数件追加しても50件制限に収まるよう余裕を持たせました。

まとめ

  • Zephyrというテストマネジメントツールについて、Chrome拡張機能を公開していました
  • 要望を出しているものの、その間にもできるだけ多くの人に便利に使ってもらえるように機能を追加しています
  • 今回は地味ですが、特定のフォルダ配下に属するテストケースを一括選択する機能を実装しました

公式に対応いただければ順次機能を削除していくつもりですが、それまで何か不便なことを見つけた場合は、随時機能を追加していきたいと思います。

何かフィードバックがあればこちらのリポジトリに Issue を作成いただけますと、対応ができるかもしれません。もし興味があれば Chrome拡張やこの記事やリポジトリにスターをいただけると、励みになりますので気が向けばお願いいたします。

https://github.com/bun913/chrome-extension-zephyr-ui-extension

以上、最後までお読みいただいてありがとうございました。

GitHubで編集を提案
Money Forward Developers

Discussion