TECH PLAY

AGEST

AGEST の技術ブログ

463

こんにちわ。GS です。 今回は、playwright-mcp を駆使して、AI を活用したソフトウェアテストの設計から実行、結果の出力に至るまでの様々な工程の自動化を試みていきます。 キーとなる技術は、 MCP Playwright Aria snapshots LLM の3つです。 前知識 まずは今回使用する技術や概念について説明します。 MCP(model context protocol)とは MCP は「Model Context Protocol」の略で、AI モデル(LLM)が外部のデータソースやツールと通信するための標準化されたプロトコルです。 MCP をわかりやすく説明すると MCP は、「AI のための USB-C」のようなものと考えてください。 例えば、あなたが持っている様々な家電(テレビ、スピーカー、照明、コーヒーマシンなど)を 1 つのリモコンで操作できるユニバーサルリモコンをイメージしてください。MCP は AI アシスタントにとってのそのユニバーサルリモコンです。 従来、AI モデル(ChatGPT、Claude、LLaMA など)が外部のシステム(データベース、API、社内文書など)と連携するには、それぞれのシステムごとに専用の接続方法を開発する必要がありました。これは、テレビ、エアコン、照明器具などにそれぞれ別のリモコンが必要なようなものです。 MCP はこの問題を解決し、AI モデルと外部ツールの間の「共通言語」を提供します。これにより: 開発者は各 AI モデルと外部ツールの組み合わせごとに独自の連携方法を作る必要がなくなります ユーザーは AI アシスタントに「今日のサンフランシスコの天気は?」と聞くだけで、AI が適切な外部ツールを使って最新情報を取得できます 新しいツールやデータソースを簡単に AI システムに追加できるようになります 2024 年末に Anthropic によって公開された MCP は、オープンスタンダードとして急速に普及し、多くの開発者がさまざまなツールやサービスと AI を連携させるためのサーバーを開発しています。 Playwright とは Playwright は、Microsoft が開発したブラウザ自動化ツールです。 簡単に言うと、人間がブラウザで行う操作(ウェブサイトを開く、ボタンをクリックする、テキストを入力するなど)をコンピュータが自動的に行えるようにするソフトウェアです。 例えば、オンラインショッピングサイトで商品を検索したり、フォームに情報を入力したり、ログインしたりといった作業を、人間が手動でやる代わりに自動的に実行できます。 これは特にウェブサイトのテストや、繰り返し行う作業の自動化に役立ちます。 playwright-mcp とは playwright-mcp は、Microsoft の Playwright チームが開発した MCP(Model Context Protocol)サーバーで、AI アシスタントがウェブブラウザを操作できるようにするツールです。このサーバーは、構造化されたアクセシビリティスナップショットを通じてウェブページとの対話を可能にし、スクリーンショットや視覚ベースのモデルを必要としない特徴があります。 playwright-mcp の主な機能 playwright-mcp の主な特徴は以下の通りです: 高速で軽量 :Playwright のアクセシビリティツリーを使用し、ピクセルベースの入力に依存しません LLM フレンドリー :視覚モデルを必要とせず、純粋に構造化データで動作します 決定論的なツール適用 :スクリーンショットベースのアプローチでよくある曖昧さを回避します playwright-mcp を使用すると、AI アシスタント(Claude や GPT-4 など)は以下のようなウェブブラウザの操作を行うことができます: ウェブページの閲覧・ナビゲーション テキスト入力やボタンのクリック ページ内の要素の検索と情報取得 フォームの入力と送信 構造化されたコンテンツからのデータ抽出 Aria Snapshot とは Aria Snapshot は、Playwright が提供するウェブページのアクセシビリティ構造をテストするための機能です。この機能は、HTML の構造をアクセシビリティツリーの YAML 表現として提供し、ページの状態を検証するために使用されます。 特徴 アクセシビリティツリーの表現 : Aria Snapshot は、DOM の構造ではなく、アクセシビリティツリーを基にしています。これには要素の役割、名前、状態などの情報が含まれます。 YAML 形式 : スナップショットは YAML 形式で表現され、人間にも読みやすい形式で保存されます。 柔軟な比較 : 部分的なマッチングや正規表現を使用した比較が可能で、動的なコンテンツにも対応できます。 強み リファクタリング耐性 : DOM の内部構造が変更されても、アクセシビリティツリーは変わりにくいため、リファクタリングに強いテストが可能です。 アクセシビリティの検証 : アクセシビリティの観点からページ構造を検証できるため、支援技術との互換性を確保しやすくなります。 視覚に依存しないテスト : 見た目ではなく、構造的な変更を検出できるため、CSS の変更などに影響されにくいテストが可能です[1]。 弱み 詳細な視覚的テストには不向き : レイアウトや色などの視覚的な要素のテストには適していません。 学習コスト : アクセシビリティツリーの概念を理解する必要があり、初心者には難しい場合があります。 他の技術との違い 従来の DOM スナップショットとの違い : DOM の構造ではなく、アクセシビリティツリーを比較するため、内部実装の変更に強いテストが可能です。 ビジュアルリグレッションテストとの違い : 視覚的な差異ではなく、構造的な差異を検出するため、異なる目的で使用されます。 YAML 表現の例 以下は、シンプルな HTML とそれに対応する Aria Snapshot(YAML 表現)の例です: HTML: <nav> <ul> <li><a href="/">ホーム</a></li> <li><a href="/about">概要</a></li> <li><a href="/contact">お問い合わせ</a></li> </ul> </nav> Aria Snapshot(YAML 表現): - navigation: - list: - listitem: - link "ホーム" - listitem: - link "概要" - listitem: - link "お問い合わせ" この例では、ナビゲーション構造がアクセシビリティツリーとして表現されており、各要素の役割と名前が明確に示されています。 playwright-mcp での活用 playwright-mcp では、この Aria snapshots を活用することで、AI アシスタントがウェブページの構造を理解し、適切な操作を行うことができます。視覚的な情報に依存せず、構造化されたデータのみを使用するため、軽量かつ高速な処理が可能になり、テキストベースの LLM でも効果的にウェブブラウザを操作できるという大きな利点があります。 使用例 playwright-mcp の典型的な使用例には以下のようなものがあります: ウェブナビゲーションとフォーム入力 構造化されたコンテンツからのデータ抽出 LLM による自動テスト エージェントのための汎用ブラウザ操作 バックグラウンドまたはバッチ操作(ヘッドレスモード) 導入方法 playwright-mcp は、npm 経由で簡単に導入できます。以下は基本的な設定例です: { "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } } ヘッドレスモード(GUI なしのブラウザ)で実行する場合は以下のように設定します: { "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest", "--headless"] } } } 実行前準備 MCP サーバーを起動する方法は色々ありますが、今回使用する playwright-mcp サーバーをローカルの Node.js を使用して起動してみます。 Node.js そのもののインストール方法についての詳しい説明は割愛します。ちなみに筆者は Windows も Mac も mise を使ってインストールしています。 mise use -g node@lts npx コマンドの確認 Node.js がインストールされていれば、以下のコマンドで npx コマンドが使用できるはずです。 npx --version npx コマンドのパス確認 npx コマンドのパスを確認します。 Mac の場合 which npx Windows の場合 where npx 操作ツール MCP サーバーを呼び出せるツールなら何でもいいのですが、今回は  Claude のデスクトップアプリ  を使ってみます。 Claude Desktop の設定画面より、構成を編集を押します。 claude_desktop_config.json をお好きなエディタで開きましょう。 開いたファイルに以下の内容を追記します。今回設定する MCP サーバーは、アクセシビリティスナップショットを用いて操作をおこなう MCP サーバーです。 { "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } } 設定が完了したら、Claude Desktop を再起動します。 正しく設定されていると、以下のように MCP サーバーが追加されているのが確認できるはずです。 設定がうまくいかない場合、command の部分をフルパスにすることで解消する可能性があります。 たとえば mise を使ってインストールした Node.js に付随する npx コマンドのパスは Mac の場合 "command": "/Users/{ユーザー名}/.local/share/mise/installs/node/22.14.0/bin/npx" Windows の場合 "command": "C:\Users\{ユーザー名}\scoop\apps\mise\current\mise\installs\node\22.14.0\npx.cmd" のようなパスになります。  ●ヒント MCP を使える MCP クライアントにはどんなものがある? ・ Visual Studio Code ・ Cursor ・ Visual Studio Code や Cursor で使える拡張機能の一つである Cline ・ 自作した MCP クライアント など様々な選択肢があります。 playwright-mcp の実行 実際に実行して、様々な動作を確認しながら、テストに活用できる具体例を紹介します。 MCP サーバーに実行してほしい操作を伝えると、指示通りに実行されます。 実行時には、「この操作を本当に実行してもよいですか?」といった確認メッセージが表示されることがあります。 「このチャットで許可」を選択すると、同じ種類の操作については以降確認なしで自動的に実行されるようになります。 ウェブサイトの構造を確認してみよう まずは MCP サーバーにウェブサイトの構造を確認してもらい、正しく動作していることを確認してみましょう。 以降 Web サイトに対する操作は、弊社サイト「 Sqripts 」を対象とします。 以下の命令を与えると、サイトの構造を tree コマンド形式で出力してくれます。 https://sqripts.com このサイトの構造をtreeコマンド形式で出力してください。 このように、サイトの構造を tree コマンド形式で出力してくれます。 テストケースを生成してみよう サイトの構造を確認したところで、テストケースを生成してみましょう。 今回はトップページ だけ のテストケースを生成してみます。 https://sqripts.com このページの内容から、このページのためのテストケースを生成してください。 以下が実際に生成されたテストケースのマークダウンです。 # Sqripts.com のテストケース ## 1. ナビゲーションとリンクテスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |1.1|ヘッダーナビゲーションリンクの動作確認|Sqripts.comのトップページにアクセスする|1. 各ナビゲーションリンク(テクノロジー、品質、エンジニアリング、スクリプター、特集、ニュース、資料ダウンロード、Sqriptsについて)をクリックする|各リンクをクリックすると対応するページに正しく遷移する| |1.2|「新規登録・ログイン」リンクの動作確認|Sqripts.comのトップページにアクセスする|1. 「新規登録・ログイン」リンクをクリックする|ログインページに正しく遷移する| |1.3|フッターリンクの動作確認|Sqripts.comのトップページにアクセスする|1. フッター内の全てのリンクを一つずつクリックする|各リンクが正しく対応するページに遷移する| |1.4|記事カテゴリタグリンクの動作確認|任意の記事ページを開く|1. 記事に付与されているカテゴリタグ(品質、エンジニアリング、ソフトウェアテストなど)をクリックする|対応するカテゴリページに正しく遷移する| ## 2. コンテンツ表示テスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |2.1|おすすめ記事セクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「RECOMMEND おすすめ記事」セクションを確認する|おすすめ記事が正しく表示され、タイトル、日付、カテゴリ、著者情報が表示されている| |2.2|最新記事セクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「LATEST 最新記事」セクションを確認する<br>2. 複数の記事が表示されていることを確認する|複数の最新記事がサムネイル画像、タイトル、日付、カテゴリ、著者情報と共に表示されている| |2.3|ランキングセクションの表示確認|Sqripts.comのトップページにアクセスする|1. 「RANKING アクセスランキング」セクションを確認する|人気記事が順位付けされて表示されている| |2.4|著者情報の表示確認|任意の記事ページを開く|1. 記事内の著者情報(名前、画像)を確認する|著者の名前と画像が正しく表示されている| |2.5|記事本文の表示確認|任意の記事ページを開く|1. 記事のタイトル、日付、カテゴリ、本文を確認する|記事の全コンテンツが正しく表示されている| ## 3. 機能テスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |3.1|「もっと見る」ボタンの動作確認|Sqripts.comのトップページにアクセスする|1. 最新記事セクション下部の「もっと見る」リンクをクリックする|記事一覧ページに正しく遷移し、より多くの記事が表示される| |3.2|タグによる記事絞り込み機能確認|Sqripts.comのトップページにアクセスする|1. 「#TAGS 人気のタグ」セクションから任意のタグ(例:「AI」「ソフトウェアテスト」)をクリックする|選択したタグに関連する記事のみが表示されるページに遷移する| |3.3|イベント・ニュースバナーの確認|Sqripts.comのトップページにアクセスする|1. 「EVENT・NEWS」セクションのバナーをクリックする|バナーに対応するイベントページやニュースページに正しく遷移する| ## 4. レスポンシブデザインテスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |4.1|モバイル表示確認|モバイルデバイスまたはブラウザの開発者ツールでモバイル表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面をスクロールし、各セクションの表示を確認する|全てのコンテンツがモバイル画面に適切に表示され、レイアウトが崩れない| |4.2|タブレット表示確認|タブレットデバイスまたはブラウザの開発者ツールでタブレット表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面をスクロールし、各セクションの表示を確認する|全てのコンテンツがタブレット画面に適切に表示され、レイアウトが崩れない| |4.3|画面回転時の表示確認|モバイルデバイスまたはブラウザの開発者ツールでモバイル表示を有効にする|1. Sqripts.comのトップページを表示する<br>2. 画面を横向きに回転させる|横向き表示でもコンテンツが適切に表示される| ## 5. パフォーマンステスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |5.1|トップページの読み込み速度確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. Sqripts.comのトップページをリロードする<br>3. 読み込み完了時間を確認する|ページの読み込み時間が3秒以内である| |5.2|画像の最適化確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. Sqripts.comのトップページをリロードする<br>3. 画像ファイルのサイズを確認する|画像が適切に最適化されており、大きなファイルサイズの画像がない| |5.3|記事ページの読み込み速度確認|ブラウザの開発者ツールを開く|1. 開発者ツールのNetworkタブを有効にする<br>2. 任意の記事ページを開く<br>3. 読み込み完了時間を確認する|記事ページの読み込み時間が3秒以内である| ## 6. 機能性テスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |6.1|検索機能の動作確認|Sqripts.comのトップページにアクセスする|1. 検索ボックスにキーワード(例:「テスト自動化」)を入力する<br>2. 検索を実行する|入力したキーワードに関連する記事が検索結果に表示される| |6.2|新規登録機能の確認|「新規登録・ログイン」ページにアクセスする|1. 新規登録に必要な情報を入力する<br>2. 登録ボタンをクリックする|アカウントが正常に作成され、ログイン状態となる| |6.3|ログイン機能の確認|「新規登録・ログイン」ページにアクセスする|1. 既存アカウントの情報を入力する<br>2. ログインボタンをクリックする|正常にログインでき、ログイン状態となる| ## 7. アクセシビリティテスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |7.1|画像の代替テキスト確認|ブラウザの開発者ツールを開く|1. トップページの画像要素を検査する<br>2. alt属性の値を確認する|全ての重要な画像に適切な代替テキストが設定されている| |7.2|キーボードナビゲーション確認|Sqripts.comのトップページにアクセスする|1. マウスを使用せず、Tabキーのみでページ内を移動する<br>2. Enterキーでリンクを開く|キーボードのみでページのすべての機能にアクセスできる| |7.3|フォントサイズの変更確認|Sqripts.comのトップページにアクセスする|1. ブラウザの設定でフォントサイズを大きくする(Ctrl + または Cmd +)|コンテンツが読みやすく表示され、レイアウトが崩れない| ## 8. セキュリティテスト |ID|テスト項目|前提条件|テスト手順|期待結果| |---|---|---|---|---| |8.1|HTTPSプロトコルの確認|ブラウザでSqripts.comにアクセスする|1. URLバーの鍵アイコンを確認する|サイトがHTTPSで保護されている| |8.2|パスワード強度の確認|「新規登録・ログイン」ページにアクセスする|1. 新規登録フォームで弱いパスワードを入力する|強度が不足しているパスワードを拒否または警告が表示される| ## 9. クロスブラウザテスト | ID | テスト項目 | 前提条件 | テスト手順 | 期待結果 | | --- | ------------ | ---------------------- | ------------------------------------------------------------------------- | ---------------------- | | 9.1 | Chrome互換性確認 | Google Chromeブラウザを起動する | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する | | 9.2 | Firefox互換性確認 | Firefoxブラウザを起動する | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する | | 9.3 | Safari互換性確認 | Safariブラウザを起動する | 1. Sqripts.comのトップページにアクセスする<br>2. 各セクションの表示を確認する<br>3. リンクをクリックして動作を確認する | すべての機能とデザインが正常に表示・動作する | このように、AI がテストケースを自動生成してくれました。 今回はあえて簡潔な指示だけで生成してみましたが、より具体的なテストケースが必要な場合は、テスト観点や重要なポイントを詳細に入力することで、それらの指示に沿ったテストケースを生成できます。 要件定義書や基本設計書、詳細設計書などを入力し、適切なプロンプトを与えれば、対象画面と設計書の仕様を照合したテストケースを生成することも可能です。 生成されたテストケースに修正や追加が必要な場合は、具体的な指示を入力するだけで、AI が修正や加筆を行ってくれます。 テストケースを実行してみよう 生成されたテストケースを元に、テストを実行していきます。しかし単純に実行するだけでは、テストの再利用性が確保できません。 そこで、テストを実行しながら、同時にそのテストを再利用可能な形式でアウトプットする方法を検討しました。 今回は、playwright-mcp で実施されているテストを、TypeScript + Playwright コードとして出力することにします。 以下は使用したプロンプトです。 「1.1ヘッダーナビゲーションリンクの動作確認」のテストをplaywrightで操作して実行し、その実行した手順をtypescript + playwrightコードとしてまとめ、最終レポートにテスト結果と、そのテストを再現できるまとめたコードをレポートとして出力してください。 今回の例では、元となるテストケースの抽象度が高く、そのままではテスト実行が困難でしたが、 実行過程でより具体的なテストケースが自動生成 され、同時にテスト実行も完了してレポートが作成されました。 この結果から、「テストケースを抽象から具象(ステップ)へと変換する」能力が明確に見て取れ、さらに実際の実行までを一貫して行える点が、このテストケース生成システムの大きな強みだと言えます。 もちろん、すべての状況でこれが最適解というわけではなく、ケースによっては適していない場合もあるでしょう。 しかし、このようなテストケース生成システムは、効率的かつ効果的なテスト設計において非常に価値のある強力なツールであることは間違いありません。 作成されたテストコードを実行してみよう 以下が作成されたテストコードです。 このテストコードでは、スクリーンショットを取得していますが、スクリーンショット名にユニーク性がないため、複数のブラウザで実行した場合、後から実行したブラウザのスクリーンショットで上書きされてしまう問題があります。 この問題を解決するため、スクリーンショット名にユニークな値を含めるように修正しました。 また、ファイル名がテストファイルの命名規則に沿っていなかったため、適切な名称に変更しました。 // navigation.spec.ts - Sqripts.comヘッダーナビゲーションリンクのテスト import { test, expect } from "@playwright/test"; test("1.1 ヘッダーナビゲーションリンクの動作確認", async ({ page }) => { // ナビゲーションリンクとその期待されるURLを定義 const navLinks = [ { name: "テクノロジー", url: "https://sqripts.com/category/technology/" }, { name: "品質", url: "https://sqripts.com/category/quality/" }, { name: "エンジニアリング", url: "https://sqripts.com/category/engineering/", }, { name: "スクリプター", url: "https://sqripts.com/writer/" }, { name: "特集", url: "https://sqripts.com/feature/" }, { name: "ニュース", url: "https://sqripts.com/news/" }, { name: "資料ダウンロード", url: "/document/" }, { name: "Sqriptsについて", url: "https://sqripts.com/about/" }, ]; // テスト結果を保存する配列 const results = []; // テスト開始時刻を記録 const startTime = new Date(); console.log(`テスト開始: ${startTime.toLocaleString()}`); try { // ホームページに移動 console.log("Sqripts.comに移動中..."); await page.goto("https://sqripts.com/"); await page.waitForLoadState("domcontentloaded"); console.log("ホームページのスクリーンショットを取得"); await page.screenshot({ path: "./screenshots/homepage.png" }); // 各ナビゲーションリンクをテスト for (const link of navLinks) { try { console.log(`ナビゲーションリンクをテスト中: ${link.name}`); // ナビゲーションリンクを見つけてクリック // ナビゲーションは通常、HTMLではnavタグに含まれているため、このセレクタを使用 const linkElement = await page .locator(`nav >> text="${link.name}"`) .first(); // クリック前にスクロールして要素を表示 await linkElement.scrollIntoViewIfNeeded(); // リンク要素がクリック可能かどうかを確認 await expect(linkElement).toBeVisible(); await expect(linkElement).toBeEnabled(); // リンク要素をクリック await linkElement.click(); // ページ遷移の完了を待機 await page.waitForLoadState("networkidle"); // 現在のURLを取得 const currentUrl = page.url(); // 遷移先ページのスクリーンショットを保存 await page.screenshot({ path: `./screenshots/${link.name}-page.png` }); // 期待されるURLに遷移したかどうかを確認 // 相対URLの場合はベースURLを考慮する const expectedUrl = link.url.startsWith("http") ? link.url : `https://sqripts.com${link.url}`; const passed = currentUrl === expectedUrl || currentUrl.includes(link.url); // テスト結果を保存 results.push({ link: link.name, expectedUrl: expectedUrl, actualUrl: currentUrl, passed, }); // コンソールにテスト結果を出力 if (passed) { console.log(`✅ ${currentUrl} に正常に遷移しました`); } else { console.log( `❌ 遷移に失敗しました。期待値: ${expectedUrl}, 実際: ${currentUrl}` ); } // 次のテストのためにホームページに戻る await page.goto("https://sqripts.com/"); await page.waitForLoadState("domcontentloaded"); } catch (error) { console.error(`エラー発生 ${link.name}のテスト中: ${error}`); results.push({ link: link.name, expectedUrl: link.url, actualUrl: "Error", passed: false, error: error.toString(), }); } } } catch (error) { console.error(`ホームページへの移動に失敗: ${error}`); } // テスト終了時刻を記録 const endTime = new Date(); const testDuration = (endTime.getTime() - startTime.getTime()) / 1000; console.log(`テスト終了: ${endTime.toLocaleString()}`); console.log(`テスト所要時間: ${testDuration}秒`); // テスト結果レポートを生成 let passCount = 0; let failCount = 0; console.log("\n========== テスト結果レポート =========="); console.log("ヘッダーナビゲーションリンクテスト結果:"); console.log("==================================="); for (const result of results) { if (result.passed) { passCount++; console.log(`✅ ${result.link}: 成功`); console.log(` 期待値: ${result.expectedUrl}`); console.log(` 実際: ${result.actualUrl}`); } else { failCount++; console.log(`❌ ${result.link}: 失敗`); console.log(` 期待値: ${result.expectedUrl}`); console.log(` 実際: ${result.actualUrl}`); if (result.error) { console.log(` エラー: ${result.error}`); } } console.log("-----------------------------------"); } console.log(`\n概要: ${passCount}成功, ${failCount}失敗`); console.log("==================================="); // すべてのナビゲーションリンクが正常に動作したことを検証 expect(failCount).toBe(0); }); テストコードを動かすための設定ファイルです。 こちらは自動出力されたものをそのまま使用しています。 この設定は Chromium、Firefox、Webkit の 3 つのブラウザ(エンジン)で実行するように最初から設定されていました。 // playwright.config.ts - Playwrightの設定ファイル import { PlaywrightTestConfig } from "@playwright/test"; const config: PlaywrightTestConfig = { testDir: "./tests", timeout: 60000, // タイムアウトを60秒に設定 reporter: [ ["html"], // HTMLレポートを生成 ["list"], // コンソールに結果リストを表示 ["json", { outputFile: "test-results.json" }], // JSON形式のレポートも生成 ], use: { // ブラウザの設定 headless: false, // テスト実行時にブラウザを表示(視覚的に確認するため) viewport: { width: 1280, height: 720 }, // ブラウザのビューポートサイズ ignoreHTTPSErrors: true, // HTTPS証明書エラーを無視 screenshot: "only-on-failure", // 失敗時のみスクリーンショットを撮影 video: "on-first-retry", // 最初の再試行時にビデオを記録 trace: "on-first-retry", // 最初の再試行時にトレースを記録 // アクションのタイムアウト設定 actionTimeout: 10000, // アクション(クリックなど)のタイムアウトを10秒に設定 navigationTimeout: 15000, // ナビゲーション(ページ遷移)のタイムアウトを15秒に設定 }, // 並列実行の設定 workers: 1, // シーケンシャルにテストを実行(ナビゲーションテストの場合は順序が重要) // プロジェクト固有の設定 projects: [ { name: "chromium", use: { browserName: "chromium" }, }, { name: "firefox", use: { browserName: "firefox" }, }, { name: "webkit", use: { browserName: "webkit" }, }, ], // フォルダ構造の設定 outputDir: "test-results/", // テスト結果の出力ディレクトリ }; export default config; 以下のコマンドを実行してテスト環境を構築しましょう。 macOS の場合 # 新しいディレクトリを作成 mkdir sqripts-test cd sqripts-test # npm プロジェクトを初期化 npm init -y # Playwright をインストール npm install -D @playwright/test # Playwright ブラウザをインストール npx playwright install # スクリーンショットを保存するディレクトリを作成 mkdir screenshots mkdir tests touch tests/navigation.spec.ts touch playwright.config.ts Windows の場合 # 新しいディレクトリを作成 mkdir sqripts-test cd sqripts-test # npm プロジェクトを初期化 npm init -y # Playwright をインストール npm install -D @playwright/test # Playwright ブラウザをインストール npx playwright install # スクリーンショットを保存するディレクトリを作成 mkdir screenshots # テストディレクトリとファイルを作成 mkdir tests New-Item -Path tests/navigation.spec.ts -ItemType File New-Item -Path playwright.config.ts -ItemType File tests/navigation.spec.ts と playwright.config.ts ファイルに、それぞれ上記のコードを記載しました。 最後にテストを実行してみます。 npx playwright test ブラウザごとにテストが正常に実行されていることが確認できます。 WebKit はヘッドレスモードで動作しているようです(他のウィンドウの背後に隠れている可能性もあります)が、その他のブラウザは問題なく動作しています。 すべてのブラウザのスクリーンショットは screenshots フォルダに正しく保存されています。 ちなみに今回のテスト動画をよく見ると、Firefox では途中からレイアウトが崩れている箇所があります。 今回のテストケースにはレイアウトのテストが含まれていないため問題なく成功していますが、レイアウトに関するテストケースを作成する場合は、視覚的な検証を行うことでこのような問題を検出できるでしょう。 視覚的な検証を行うには、単純に考えると playwright-mcp サーバーを ビジョンモード で動作させる必要があるでしょう。 ただし、今回のテストのように途中でスクリーンショットを撮影している場合は、これらのスクリーンショットを LLM に渡すことでもレイアウトの検証が可能かもしれません。 まとめ playwright-mcp を使って テストケースを生成 テストケースの具象化(ステップ化) テストケースを実行 テストケースを再利用可能な形式で出力 テストの再実行 結果レポートの生成 これらの機能を活用し、AI を用いたソフトウェアテストを実施しました。 さらに別の技術やMCP、ソフトウェアに関するドキュメントと組み合わせれば テスト結果から仕様書の記載漏れを検出 テスト結果と仕様書を突き合わせて想定外の仕様を検出 NGテストとGithub MCPを組み合わせて不具合箇所を特定 テスト結果に基づく改善点をGithub MCPと連携してリファクタリングを実施 などの様々な活用方法が考えられます。 実際、これらの機能を提供しているプロダクトやサービスはすでに登場しています。 人の手で行わなければならない作業は確実に減少しています。今回紹介した例は単体タスクの依頼であり、自律的なエージェントはまだ登場していません。 しかし、十分な精度を持つ自律型エージェントが登場すれば、人間が行うべき作業は限りなく0に近づいていくでしょう。 1年後にはどのようなソフトウェアテストが可能になっているでしょうか。 1年と言わずとも、わずか1〜2ヶ月で技術が劇的に進化する可能性もあります。 そのような変化が起きた際には、また新たな記事でご紹介したいと思います。  The post 【自動化】playwright-mcpを駆使し、ソフトウェアテストの設計から実行、テスト結果の出力までの自動化を試みる first appeared on Sqripts .
アバター
帰納的な推論 と 発見的な推論(アブダクション) は、 私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。 それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意すると質の高い思考ができるのか、基本知識を押さえておくと実務のレベルアップにつながります。 <実務三年目からの発見力と仮説力 記事一覧> ※クリックで開きます 【第1回】見つけるための論理【連載初回、全文公開中】 【第2回】 “共通項”を見つけ出す 【第3回】発見はよい観察とよい方法から 【第4回】帰納の仲間と落とし穴 -前編- 前編では「帰納的推論で気をつけたい落とし穴」についてお伝えしました。 後編となる今回は「帰納的推論の仲間」( 第2回 の続き)です。 帰納の仲間たち 帰納的な推論には 第2回 で紹介したものの他にも仲間がいます。 ここではふたつ、 類推(類比的推論) と 既知の因果関係を用いた推論 を紹介します。 (実は、どちらもこれまでの記事の中でさりげなく活躍しています……) 類推(類比的推論) 「あるものごとを他のものごとになぞらえて、共通項を見出す」「あるものごとと他のものごととの類似点を見つけ、一般化する」 といった思考の形は 類推 、 類比的推論 と呼ばれます。 有限の事例の列挙から共通項を見出し、対象全体に一般化する点で、これも帰納的な推論の仲間と言えます。 類推の形には2種類あります。 事例群αに見出された共通点を、別の事例群βの中に見出す(推論する)形 (本記事内独自の呼称として、“タイプA”と呼びます) 事例群αとβとの類似性を基に、新たな共通点を見出す(推論する)形 (本記事内独自の呼称として、“タイプB”と呼びます) 図4-4 類比的推論のふたつの形 “タイプA”では、 ①ある事例群αにおける共通項(属性/特徴/etc.)から、 ②同じ共通項を持つ別の事例群βでも同じことが言えるだろう、 と推論しています。 この形はこれまでも本連載の中でひそかに出てきています。 「ソフトウェアZがプリインストールされているスマートフォンで故障Fが起こる」では、「故障Fが起こるスマートフォンの特徴」「起こらないスマートフォンの特徴」を仕分ける際に、「同じ特徴を持っているなら、同じ故障が起こるのでは」という見方をしています。 “タイプB”はちょっと込み入っていますが、 ①ふたつの事例群α, βに共通項を見出し、 ②事例群αに新たに発見された属性/特徴に対して、 ③ 似ている 事例群βにも 同じ属性/特徴 が見られるだろう(共通項が増えるだろう)、 と推論しています。 図4-5 “タイプB”の推論の構造 類推をする上での 注意点 は、 ふたつの事例群間の共通項が多いほど、推論の蓋然性は高くなります。 既知の共通項と、新たに加わる共通項との関連が密接であるほど、蓋然性は高くなります。 図4-4の“タイプA”の例で、ソフトウェアYとZの共通項は、単に「同じようなサービスを提供する」だけよりは、「使用するリソース、必要とする権限設定、制御構造など」の類似点が多い方が、「ソフトウェアYでも同じ故障Fが起こる」見込みが高いでしょう。 (といっても、「同じようなサービスを提供する」のような目につく点に着目するのは悪手、ということではありません。調査初期の、手がかりが何もないような状況では、見えやすい類似点から手をつけることはよくあります) “タイプB”の例では、ソフトウェアZとYの共通項と故障Fとの関連が強そうで、故障Gもそれら共通項との関連が強そうなら、「Yでも故障Gが起こる」見込みは高いでしょう。 逆に故障GがZに固有の故障でありそうなら(Z独自の処理や、Zに特有のデータに関わる、etc.)、その見込みは低くなるでしょう。 なお、今回紹介した「帰納的推論の性質に関わる落とし穴」はそのまま類推でも気をつける必要があります。 既知の因果関係を用いた推論 既知の因果関係の知識を手がかりに、起こった事象から原因を(または、先行事象から起こり得る結果を)推論する、というのも一種の類推と言えるでしょう。 (たとえば、電子レンジの原理を知っていれば、実際にレンジ内で“爆発”が起こった時に何が原因か推測が働きやすいでしょうし、ある種の食品を電子レンジで温める際に注意深くなるでしょう) 図4-6 既知の因果関係を使って推論する 「ハードウェアやソフトウェアで起こりがちなトラブルの原因と事象の知識」は、問題発生時の原因の切り分けにも通じますし、エラー推測といったテスト技法とも関わります。仕入れておくに越したことはありません。 ネットワーク機器などのハードウェアで起こるトラブルと、ソフトウェアの実行に及ぼす影響 使用しているOS, ミドルウェア, サーバー等の典型的なトラブルと、それが引き起こす事象 プログラミング言語や処理系に関する知識 etc. なお、既知の因果関係の知識は推論を支えてくれはしますが、状況証拠からの推測である点、やはり蓋然的な推論になります。 事象の原因を説明する仮説 「因果関係の推定に関わる落とし穴」の「早急な特定は禁物」で触れているように、因果関係の推定は簡単にいかない場合も多々あります。 原因らしきものを挙げるにとどまらず、「それが原因だとして、どんな過程でこの結果に至ったのか」を説明する仮説( 説明仮説 )が考えられるとなおよいです。 (類推(類比推論)や既知の因果関係を用いた推論は仮説を考える助けになります) 原因から結果までの過程に矛盾がない、他の事象との整合もとれているような“よい” 説明仮説 は、原因の推定に対する確信を与えてくれますし、原因の特定作業も助けてくれます。 そこで、次回からはよい仮説を考えるためのもうひとつの推論の形である アブダクション を紹介していきます。 参考文献 近藤洋逸, 好並英司 『論理学入門』 岩波書店 1979 鈴木美佐子 『論理的思考の技法Ⅱ』 法学書院 2008 藤野登 『論理学 伝統的形式論理学』 内田老鶴圃 1968 J.S.ミル(著), 大関将一(訳) 『論理学体系 : 論証と帰納 5』 春秋社 1959 T・エドワード・デイマー(著), 小西卓三(監訳), 今村真由子(訳) 『誤謬論入門 優れた議論の実践ガイド』 九夏社 2023 図版に使用した画像の出典 Loose Drawing 人物画をお借りしています。 品質探偵コニャン:Produced by Sqripts . No Unauthorized Reproduction. The post 【第5回】帰納の仲間と落とし穴 -後編-|実務三年目からの発見力と仮説力 first appeared on Sqripts .
アバター
帰納的な推論 と 発見的な推論(アブダクション) は、 私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。 それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意すると質の高い思考ができるのか、基本知識を押さえておくと実務のレベルアップにつながります。 <実務三年目からの発見力と仮説力 記事一覧> ※クリックで開きます 【第1回】見つけるための論理【連載初回、全文公開中】 【第2回】 “共通項”を見つけ出す 【第3回】発見はよい観察とよい方法から 【第4回】帰納の仲間と落とし穴 -前編- 今回のトピックは2つ、前編では「帰納的推論で気をつけたい落とし穴」、そして後編では「帰納的推論の仲間」( 第2回 の続き)です。 帰納的推論で気をつけたい落とし穴 帰納的な推論にも落とし穴(誤謬)はあります。 見つける共通項が因果関係である場合には、因果関係の推定に関わる落とし穴もあります。 第2回 , 第3回 で説明したことも併せ、改めて今回見ていきましょう。 なお、[ 実践編 ]と同様、以下の点に注意してください。 本記事で紹介しているものがすべてではありません 。 これらの分類は排他的なものではありません。複数の分類に該当する誤りもあります(視点によって分類が変わる)。 複数の誤謬が重複したり関連したりして間違った推論を形づくることもあります。 誤謬の名称は、人により文献によって名称が異なることもあります。 帰納的推論の性質に関わる落とし穴 一般化:標本(サンプル)にまつわる落とし穴 軽率な一般化 、または 不十分な標本 の誤謬。 母集団の規模に対して少な過ぎる事例を基に一般化をしてしまう誤りです。 偏った標本 の誤謬。 数は問題ないとしても、母集団の傾向(属性/特徴の在りよう)を適切に反映できていない事例を基に一般化をしてしまう誤りです。 事例の数が少ない場合は 軽率な一般化 だけでなく 偏った標本 になっていないか気をつける必要があります。 こうしたことは、統計的な推論でなく枚挙的な帰納をする場合でも気をつけたい事柄と言えます。 (参考: 第2回 の図2-1(B)) 図2-1 帰納的な推論(再掲) 帰納的な推論ができそうな場合は、まず、 「事例の数と傾向を把握した上で推測を立てる」ことを意識して、これらの点を確かめましょう。 事例の数は、一般化するには十分そうか? (推測に合致しそうな事例だけ無意識に集めているということはないか) (数が少ない場合、推論の蓋然性が低い可能性を意識できているか) 事例は偏っていないか? (推測に合致しそうな事例だけ無意識に注目しているということはないか) (偏りがありそうなら、事例を増やして多様性を増すことはできないか) なお、「事例の数が少ないならば、帰納的推論の蓋然性は低い」、というわけではありません。 母集団の均質性、類似性が高いなら(どれも同じ属性を持っている、どれもみな似通っている、etc.)、事例の数が少なくても結論の蓋然性は見込める場合があります。 一般化:結論の導き方にまつわる落とし穴 事例の数や偏りの点で問題がなくても、共通項から結論を引き出す際の考え方や態度にも落とし穴はあります。 いずれも、共通点/類似点に対して相違点への注目が相対的に弱まってしまうところからはまる落とし穴と言えます。 キャリアX社のAndroidスマートフォンA, B, C, D, Eがあるとして、 (1)共通点や類似点にばかり注意が向いて、 相違点を見落とす 。 「A, B, C, D, EはAndroidスマートフォンだから同じだ」と考える類です。 (ハードウェアスペックもUI回りも違っている、etc.) (2)共通点や類似点と結論する性質との 関連が薄い 。 A, B, C, Dで同じ故障が起こっていることから「Eでも同じ故障が起こるだろう」と考える類です。 (見かけの共通点/類似点に引っ張られて結論に飛びついてしまう、etc.) (3)結論の 蓋然性を過度に見積もる 。 A, B, C, D, Eすべてで試したことから「この故障はすべてのAndroidスマートフォンで起こる」と考える類です。 (事例の多さや傾向の偏りのなさなどから、結論が必ず正しいと考える、etc.) (実は権限設定に問題があり、使用したスマホで同じ権限設定のミスをしていたためだった……などの可能性もあります) 図4-1 枚挙的帰納の落とし穴 統計的帰納で気をつけたいこととしては、 的外れな一般化 といったものがあります。 よく起こりがちなものは、事例の数を割合と同一視してしまう(または置き換えてしまう)、というものです。 第2回 の「A子さんの学校でのいちごフォンユーザーの割合」でいうと、 いちごフォンユーザーの数が多いならば、いちごフォンのハードウェア故障の 件数 も多いのは自然でしょう。 対して、その他のスマートフォンユーザーのハードウェア故障件数は相対的に少ないでしょう。 ここで「いちごフォンはハードウェア故障が多い」と考えるのは、ユーザー数の規模の違いを見ずに、ハードウェア故障の件数を故障を起こす割合と同一視、ないし置き換えて考えてしまっています(「故障件数が多い=故障の割合が高い」)。 より適切には、いちごフォンとその他のスマートフォンそれぞれのハードウェア故障の割合を比較するべきです。 図4-2 統計的帰納の落とし穴:的外れな一般化 因果関係の推定に関わる落とし穴 因果関係の取り違え 前後即因果 の誤謬。 時系列の前後関係を因果関係と思う 誤りです。 結果画面の表示が崩れた直後にフリーズしたことから、「表示の崩れがフリーズの原因」と考える類です。 この誤りは古くは「『この後に,だからこの故に (post hoc, ergo propter hoc)』の誤謬」と呼ばれていたそうで、昔からありがちな誤りだったのでしょうね。 原因と結果の混同 。 サブシステムAの処理の重さがサブシステムBのデータ転送遅延を引き起こしているのを、「Bの遅延がAの処理の重さの原因」と考える類です。 間違った原因探し   たまたま共存しているだけ の複数の事象の間に因果関係があると考える誤り。 サブシステムAの応答速度の低下とサブシステムBの転送遅延はたまたま同時に起こっていたただけ(互いに何の干渉もしていない)、といった類です。 相互作用の一面だけ見て 因果関係を考えてしまう誤り。 サブシステムAの応答速度の低下がサブシステムBのデータ転送遅延の原因と思ったが、それぞれの故障が互いに影響を与えていた、といった類です。 原因の見逃し 関連する原因の無視/見落とし 。 複数の原因が関連し合って生じている事象に対し(原因の多数性)、 ひとつの原因を特定するに留まり、他の原因を無視/見落としてしまう 誤りです。 取得するデータの間違えと、計算ロジックの誤りと、画面表示の処理の誤りが合併した故障を、計算ロジックの誤りにだけ注目して他を見落としてしまう類です。 共通する原因の無視/見落とし 。 複数の事象や状態が、共通する原因の結果として起こっている可能性を見落とす(そして、それら事象の間に因果関係を求めてしまう)誤りです。 モジュールAでのデータ加工の故障と、モジュールBでのデータ転送の故障は、実は中間ファイルのデータの破損が引き起こしているのに、個別の事象と判断する(場合によっては「Aの故障がBの故障を引き起こした」などと考える)類です。 早急な特定は禁物 ここまで挙げた誤りにもつながり得る落とし穴が、 因果関係の過剰な単純化 です。 「目につく」「最初に気づいた」「判りやすい」「いかにもそれらしい」といった理由から、見つかった“原因っぽいものごと”に飛びついてしまう(そこで因果関係の推定を止めてしまう)誤りです。 図4-3 因果関係推定の落とし穴 一般に、ある事象が起こった際、その要因と考えられる事柄や先行する事象は数多くあります。 複数の要因が(複雑に)関連してひとつの事象を起こすことも珍しくありません。 それらの中から原因を見つけるのは、時間や手間がかかるものです。 特に、ソフトウェアの故障や不具合発生時のような、起こった事象から遡って原因を考える場合、「事象を確認した段階で、原因の候補を洗い出して、原因らしきことを推定する」のは簡単なことではありません。 (同じようなことが、プロセス改善時の原因分析でも言えます) 因果関係を見つけようとする時には、まずこのことに気をつけましょう。 ( 第3回で紹介した「ミルの帰納法」 も参考になります) 事象や発生状況の詳細を十分調べたか? 原因の候補(先行する事象や、故障の要因になり得る事項)を十分考えて挙げたか? 見つけた(と思う)原因は、観察結果に即しているか? 原因から結果に至る道筋を単純に考えていないか? この章に挙がっている 因果関係の推定に関わる落とし穴 に落ちていないか? 別の落とし穴にはまらないように 観察結果をまとめて共通項を見つけたり、因果関係を特定しようとする際には、演繹的な論理のスキルも働きます。 演繹的推論の落とし穴( 形式面(前編) 、 非形式面(後編) )にも併せて気をつけましょう。 ★ 長くなってしまいましたので、今回はここまで。帰納の仲間については後編でお伝えします。 参考文献 近藤洋逸, 好並英司 『論理学入門』 岩波書店 1979 鈴木美佐子 『論理的思考の技法Ⅱ』 法学書院 2008 藤野登 『論理学 伝統的形式論理学』 内田老鶴圃 1968 J.S.ミル(著), 大関将一(訳) 『論理学体系 : 論証と帰納 5』 春秋社 1959 T・エドワード・デイマー(著), 小西卓三(監訳), 今村真由子(訳) 『誤謬論入門 優れた議論の実践ガイド』 九夏社 2023 図版に使用した画像の出典 Loose Drawing 人物画をお借りしています。 品質探偵コニャン:Produced by Sqripts . No Unauthorized Reproduction. 【連載】ソフトウェアエンジニアのための論理スキル[実務三年目からの発見力と仮説力] 記事一覧 【第1回】見つけるための論理 【連載初回、全文公開中】 【第2回】 “共通項”を見つけ出す 【第3回】発見はよい観察とよい方法から 【第4回】帰納の仲間と落とし穴 -前編- The post 【第4回】帰納の仲間と落とし穴 -前編-|実務三年目からの発見力と仮説力 first appeared on Sqripts .
アバター
みなさん、こんにちは。 「ソフトウェアレビューをエンジニアリングっぽく捉える会」 の”うれっしー(うれしのあや)”です。 今回は「レビューとは?」がテーマです。 「〇〇レビューと名前がついていなくても、それはレビュー!って捉えて活動していきましょう」 と言いたい、少し視野を広めていただきたい記事になります。 ▼前回の記事はこちら [#0]イントロダクション |ソフトウェアレビューをエンジニアリングっぽく語ってみる レビューとは何か? さてさて、レビューとはいったい何でしょうか? まずは気楽に、字面(じづら)として意味をとらえてみましょう。 「レビュー(Review)」は、「 re (再び)」+「 view (見る)」が合成した形になっています。 このままの意味「再び見る」のであれば、日常生活がレビューだらけです。 朝出かける時の「携帯持った、財布持った、鍵持った!」も、もう十分レビューなわけです。 次に言葉として、辞書的な意味合いを見ていきましょう。 Googleさんに聞いてみると、「Review(レビュー)には、「批評する」「復習する」「再考する」などの意味があります。 」と教えてくれました。 例えば今回のような記事を読んでいると この記事のここはいいけど、あの部分はもう少しよく書けたはず あのポイントは覚えておきたいから、もう一度チェックしておこう ちょっと引っかかった言葉があるので、別の記事も調べてみよう なんてことがあるでしょう。 たしかに、一目見ただけではなく、今一度記事を見たり頭の中で思い起こしたりして、批評も復習も再考もしています。 というわけで、これらが「レビュー」なわけです。 それは辞書ひっくり返しただけじゃないか、エンジニアリングではなく日常の話だよね、開発で役立つことが知りたいんだよ!というあなた、ここから開発っぽくなりますのでご安心ください。 開発現場における「狭義のレビュー」と「広義のレビュー」 多くの開発現場では、コードレビューや工程移行判定のレビュー、出荷判定のレビューなど、エンジニアリングとして開発プロセスの中で形が定義されていると思います。 指摘事項について合意ができるまでさらに議論したり、疑問については関係者に説明ができるような回答を用意したり、To-doリストを残して管理したりもしているでしょう。 つまり多くの方は「レビュー」と言えば、このような公式に規定されているレビューを思い浮かべるのではないでしょうか。 これらを我々は「狭義のレビュー」と捉えています。 一方、規定されているレビュー以外で、設計書やコードを読んだり、プロセスを策定したり改善したりする際も、気になったことを同じチームのエンジニアに相談に乗ってもらったり、上司に聞いてコメントをもらったりすることが多いと思います。 我々はこれらを「広義のレビュー」として捉えています。 つまり、開発やテスト、プロセスにまつわる相談も「レビュー」に入れているわけです。 「広義のレビュー」として捉えた方が、規定のレビューだけではカバーできない、今まで見えてなかったものが見えてくると思っているからです。 コードや設計書などの成果物を理解するために、 わからないことを聞いて、わかるようになる この部分は、そもそもどうなっていたのか?と確認する もっとこうした方が分かりやすいのではないか?と改善案を考える 公式レビューの準備のために、事前に合意をとっておく、有識者だけで仮の結論を出しておく このような行為を複数人で実施しているのであれば、ピアレビューと言えるのではないかと考えているわけです。 他にも、 エンジニアの頭の中にあるけど、うまく成果物に表現できていないことを引き出す 規定されたレビューの範囲内で多くの項目があり、網羅しているつもりだが、リリース後に問題が起こったので、確認項目を見直してみる 有識者が直接関係しない部分にも参加が必要になっていて時間がもったいないため、レビュー自体の手順やプロセスを効率化する これらもエンジニアリング行為であり、テクニックと同等のものを行使する必要がありますので、「レビュー」と捉えています。 にしさんがよく言っていた「テクい」話の方で、「会議術」(一般的な会議を回す技術)ではない方です。 レビューはテストとは違って動かないもの・ことも対象に入ってきますので、テストとは異なる技術が必要になることは明確でしょう。 必要な技術の中身については今後の連載の中に出てきますので、お楽しみに。 「広義のレビュー」の効果 「狭義のレビュー」の重要性は書くまでもありませんが、でき上がった後の成果物に頼ると現場の負担が大きくなりがちです。 特にレビューでお悩みの方は、公式レビューよりも前の気軽な相談や確認会を増やす=レビューをシフトレフトすると、コストをあまりかけずに製品やサービスを一歩でも改善できると思います。 加えて、レビューの役割分担も普段とは少しずらしたり別の視点にしてみたりすると、みんなの知恵や日常とは異なる良いところも見えてきそうです。 いろんな人の知恵を集めてちゃんと使えるようになると、さらに進化した、強い組織になっていくことにも繋がるはずです。 まとめ 「〇〇レビューと名前がついていなくても、それはレビュー!って捉えて活動していきましょう」 レビューを「狭義のレビュー」で捉えるよりも、「広義のレビュー」として考えてみた方が、手戻りが少なくちょっと気楽になる未来が見えてくるのではと思います。 この連載で書くのはあくまで例にはなりますが、それぞれの現場でどのようにあてはめてみると良いかを、まずはゆる目に検討されてみてください。 「広義のレビュー」の検討が、少しでも皆さまの良い製品・サービスにつながることを願っております。 この記事を担当したメンバー うれっしー (うれしのあや/ @ureshino66 ) 大規模ソフトウェアの品質管理を22年ほど経て、最近の活動は、 ASTER のバグシェルジュとSReEE(スリー)「ソフトウェアレビューをエンジニアリングっぽく捉える会:Software Review Engineering Explorers」。 https://www.softwarequasol.com/ 【連載】ソフトウェアレビューをエンジニアリングっぽく語ってみる 記事一覧 [#0]イントロダクション [#1]レビューとは? The post [#1]レビューとは?|ソフトウェアレビューをエンジニアリングっぽく語ってみる first appeared on Sqripts .
アバター
ソフトウェアクオリティマネージャーのアイネイドです。昨今、業界にはテスト自動化の波が来ており、顧客からのテスト自動化に関するご質問やご相談を受けることがあります。 そこでテスト自動化の知識をつけるために丁度よい資格試験はないものかと探していたところ「JSTQB Advanced Level テスト自動化エンジニア」という資格に辿り着きました。 本記事では「JSTQB Advanced Level テスト自動化エンジニア」試験自体についての説明および、合格に至った学習ポイントについてお話したいと思います。最後までお付き合いいただければ幸いです。 JSTQB AdvancedLevel テスト自動化エンジニア JSTQBとは何か? まずJSTQBについて知らない読者もいらっしゃると思いますので簡単に説明をします。日本におけるソフトウェアテスト技術者資格認定の運営組織として2005年4月に認定されました。各国のテスト技術者認定組織が参加しているISTQB(International Software Testing Qualifications Board)の加盟組織の一つになります。 「JSTQB Advanced Level テスト自動化エンジニア」について 本資格名である「テスト自動化エンジニア」の定義は、 テストについて汎用的で幅広い知識を持ち、テスト自動化という特定の領域につい て深く理解している者を言う。深い理解とは、組織および/またはプロジェクトが機能テストのために自動化ソ リューションを設計、開発、保守する際に、方向付けとして使用できるテスト自動化理論とプラクティスについて、 十分な知識を持っていることと定義される。 後述のシラバスより抜粋 となります。テスト自動化レベルの考え方から、ソリューションとしての運用方法まで幅広く抑えている内容となっており、コンサルタントとしての提案・マネージャーとしての運用まで実務で使うことができる「 Specialist 」として役立つ資格になっています。 なお「テスト自動化エンジニア」はAdvanced Levelのため、受験するためには「JSTQB認定テスト技術者資格Foundation Level資格試験の合格者、又は JSTQB (日本) 以外の Foundation Level 資格試験の合格者」である必要があります。ちなみに受験料は22,000円(税込)でした。  また、今回の試験は「期間限定」「受験回数制限(1回)」だったため、2024年8月1日(木) から 2024年10月31日(木)(約3ヶ月間)の期間中に一回のみ受験可能となっていました。恒常化する可能性があることは言及されていましたが、次回も期間限定である可能性がありますので「テスト自動化エンジニア」資格の取得を希望する方はアンテナを高くしておいた方がいいでしょう。 学習対象のシラバスと最小学習時間目安 学習対象となるシラバスは下記URLで公開されております。 ■テスト技術者資格制度 Advanced Level シラバス テスト自動化エンジニア https://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TAE_Version2016.J01.pdf ちなみにシラバスには章毎に学習最小時間の目安が設定されており、総合計で1170分(約20時間)となっております。これは例えば平日一日一時間の学習で約一ヶ月ということなので個人的には比較的着手しやすい資格といった印象です。 (あくまで個人的な)合格するための学習ポイント まず最初に。受験の際に秘密保持契約(NDA)を結ぶため、このコラムで試験問題や解答を示すことはありません。もし期待していた方がいましたら申し訳ございません。ただ、後述の学習ポイントを抑えることで解答しやすかったように感じましたので参考になれば幸いです。 Point1. まず頭文字の略語を把握しよう シラバスを読み始めて一番最初に思ったのがこれになります。シラバスの文章では複数の頭文字の略語が使われているのですが、似たような頭文字の略語が多いためきちんと把握してからシラバスを読み始めないと略語の意味を取り違えることが往々にあります。例えば頭文字が「TA」(Test Automation = テスト自動化)で始まる略語にはTAA、TAE、TAF、TAM、TAS等があり、略語の後に()付きで説明のように親切に記載されておらず、文章中に頻繁に登場するため時々混乱することになるでしょう。頭文字の略語を見ればすぐにイメージができる程度までしっかり覚えこんでからシラバスを読み始めるとよいでしょう。また、シラバス内の略語に関する説明はしっかり読み込んでおくことをおすすめします。 Point2. 先頭から順にシラバスを読んでいこう 他の資格であると「まずこの章から学習しよう」のような物があると思いますが、「テスト自動化エンジニア」のシラバスにおいては順番に読んでいくことをおすすめします。これはおそらくシラバスが認定コース用教材としての章立てを最初から意識して構成されており、順番に読んでいくことにより順次習得しやすく構成されているためになります。 Point3. 図をしっかり頭に入れよう シラバス内には少ないですが図がいくつか載っています。ただなんとなく図を見るのではなく、せっかく図になっているのですから、「矢印があればどこからどこにひかれている矢印なのか」や、「枠で括られている場所・中に何が記載してあるのか」を意識してはしっかり覚えておきましょう。単に文章を丸暗記するより断然効率的で頭に入っていれば問題に対して応用が効くことでしょう。 Point4. キーワードは表にまとめよう 人によるとは思いますが、私としてはシラバスで形式立てて記載(「3.2.2 テスト自動化へのアプローチ」のようなの主な概念・利点・短所など)をされている部分に関しては自分の言葉で表形式化することで理解しやすくなりました。長い文章を長いまま暗記するのはあまり現実的ではないので、一度試してみてはいかがでしょうか。 考察・まとめ いろいろと学習ポイントについて話させていただきました。 テスト自動化エンジニアは個人的にはとっつきやすく、仕事に役立ち、興味のある分野であったこともあり楽しく学習することができました。 Advanced Levelではありますが、難易度はそれほど高いわけではなくシラバスのボリュームも程々なので皆さんも一度取り組んでみてはいかがでしょうか。 本ブログを最後まで読んでいただいてありがとうございました。 The post JSTQB Advanced Level テスト自動化エンジニア試験合格体験記 first appeared on Sqripts .
アバター
こんにちは、エンジニアのタカです。 突然ですが、Google Apps Script(以下、GAS)を実装していて、もっと効率的に作業したいと思ったことはありませんか? GASは手軽に業務効率化できる便利なツールですが、コード管理やデプロイの面で課題を感じている方もいるかもしれません。この記事では、GAS開発の課題を解決するツール「clasp」を既存のGASプロジェクトに導入する手順を解説します。 claspとは GitHub – google/clasp: Command Line Apps Script Projects claspは、Googleが提供するNode.jsのパッケージで、開発者がGASをより効率的に実装、バージョン管理、デプロイができるようにします。 claspを導入することで、具体的には以下のような利点があります。 ローカル開発環境の構築 claspを使用することで、ローカル環境で任意のエディタやIDEを利用して実装できます。GASはプロジェクトのページに専用のエディタが提供されていますが、このエディタでの開発と比べ、コード補完やリファタクリング機能などが強力になるメリットがあります。 TypeScriptの利用 claspは実装言語にTypeScriptを選択できます。TypeScriptで実装することで、型安全性の保証や、コードの可読性や保守性が期待できるため、直接GASを実装するよりもバグの発生を減少させることが期待できます。 バージョン管理の容易さ ローカル環境で実装したプログラムファイルや設定ファイルは、gitで管理することができます。GASのプロジェクトページでは手動でバージョン管理が必要ですが、gitでの管理のほうが、変更履歴を追跡したり、過去のバージョンに戻したりすることが簡単になります。 デプロイの簡素化 GASのプロジェクトページではデプロイは手動で行いますが、claspを使用すると、TypeScript等で実装したファイルをコマンドで本来のGASの実行環境にpushしデプロイします。コマンドラインでデプロイができるため、手動でのデプロイと比べて開発の効率が向上します。 既存の運用方法についての悩み 以前、私はGASでシステム仕様を管理する記事を書きましたが、この記事で紹介したGASを本格的にシステムの開発と運用で用いるようになりました。 スプレッドシート × Google Apps Scriptでシステム仕様をシンプルに管理! こんにちは、エンジニアのタカです。普段はアジャイル開発におけるスクラムマスターや開発者としてプロダクトの開発に関わっています。今回は、プロダクト開発で起きたシステム課題に対して、導入の敷居が低いスプレッドシートを中心に解決を行った体験談を書きたい...  続きを読む  Sqripts 関連記事|Sqripts また、この記事とは別のGASも開発と運用で使い始めており、以下の課題を解決するため、claspを導入することにしました。 clasp導入の背景 GASのバージョン管理が煩雑 GASのファイル変更履歴はブラウザ上の専用のエディタでのみ確認でき、かつ以前のバージョンへの復元がプロジェクト全体でしか行えない。 回避手段として、GASのファイルをコピー&ペーストしてGitHubにプッシュしているが、手順が煩雑。 解決策:webエディタは使わず、最初からローカルで実装と gitでのバージョン管理を行う GASのデプロイが手動 GASプロジェクトのデプロイボタン押下でデプロイを行っており、効率がやや悪い。 解決策: claspでコマンドラインからデプロイする ローカル開発環境がない 実装を専用のブラウザ上のエディタで行っており、コード補完やリファクタリング機能が不足している。 解決策: claspで任意のエディタを使用する claspで管理するGASについて 今回の記事で取り上げるGASですが、前回の記事のコードは若干長いため、簡略化した専用のGASを準備しました。 GASは2ファイルで、処理の内容としては、スプレッドシートから値を読み取り、JSON形式の値に変換のうえ、ドライブに値をテキストファイルとして保存するものです。 なお、テキストファイルを出力するドライブのパス(ID)は、GASのスクリプトプロパティとして登録しておきます。 サンプルのスプレッドシート // JSON生成処理 function generateJson() { // スプレッドシートのデータを取得する const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_sheet"); const data = sheet.getDataRange().getValues(); // JSONを格納するオブジェクトを作成する const json = {}; // シートの各行を処理する for (let i = 0; i < data.length; i++) { json["app_PJ1_" + i] = { number: data[i][0], app: data[i][1] }; } return json; } // メイン関数 function main() { saveDrive(generateJson()); } // Google Driveにファイルを保存 function saveDrive(message) { // Google Driveの特定のフォルダにファイルを作成 const folderId = PropertiesService.getScriptProperties().getProperty( "DRIVE_FILE_PATH_PJ1" ); const folder = DriveApp.getFolderById(folderId); folder.createFile( "sample.json", JSON.stringify(message), MimeType.PLAIN_TEXT ); } clasp導入の流れとしては以下の手順で行います。 リポジトリに元のGASをpushしておく 当該リポジトリをcloneしてclaspをインストールし設定を行う GASをTypeScriptで書き換え、リポジトリにファイルをpushする claspでデプロイする なお、本来のGASのプロジェクトは2つ存在するため、前述のGASファイルをコピーし、それぞれ別のプロジェクトのGASと仮定して移行を進めます。 以下が、元のGASファイルをpushした状態のリポジトリのディレクトリ構成です。 . ├── README.md ├── project1 │ ├── drive.gs │ └── main.gs └── project2 ├── drive.gs └── main.gs claspのインストールと設定 Node.jsのインストール claspはNode.jsのパッケージなので、まずはNode.jsのインストールを行い、npmコマンドを使えるようにします。インストールは、下記の記事で解説しているasdfなどで行うのがおすすめです。 Windowsユーザーにささぐ、WSL2を利用した(ちょっと便利な)Linux開発環境作成 こんにちは。GSです。今の時代、開発から運用までLinuxを必要とするケースはとても多いです。WindowsユーザーがLinux環境が必要な開発を行うとき、WSL2を使うことで手軽に環境を作り利用することができます。「Windowsは使えるが、Linuxはよくわからない」といった人...  続きを読む  Sqripts 関連記事|Sqripts claspのインストールと設定 次に、npmコマンドでclaspをインストールし、初期設定を行います。 # package.json作成 npm init -y # claspをインストール npm install @google/clasp # コーディング時に、GASの関数を表示してくれるようになるパッケージ npm install @types/google-apps-script # Googleアカウントでログインします (認証画面が表示されるので許可します) clasp login 続いてclaspのコマンドで設定ファイルを作成します。今回は既存のスプレッドシートを使用するため、IDを指定します。プロジェクト単位で npm initを実行していますが、これは、claspのデプロイ時にプロジェクト単位で package.json が必要なためです。 # それぞれのプロジェクトで、既存のidを使用してclaspプロジェクトを作成 cd project1 npm init -y clasp create --title "Project1" --rootDir ./ --parentId "<スプレッドシートのID>" cd ../ cd project2 npm init -y clasp create --title "Project2" --rootDir ./ --parentId "<スプレッドシートのID>" コマンドを実行するとclaspの設定ファイルが生成され、同時にGASのプロジェクトも新規作成されます。 なお、作成後にスプレッドシートからGASのプロジェクトを開こうとすると、スプレッドシートに紐付いているプロジェクトが複数あるため、プロジェクトの選択画面が表示されるようになります。 ここまでのディレクトリ構成 . ├── node_modules ├── README.md ├── package-lock.json ├── package.json ├── project1 │ ├── .clasp.json │ ├── appsscript.json │ ├── drive.gs │ ├── main.gs │ └── package.json └── project2 ├── .clasp.json ├── appsscript.json ├── drive.gs ├── main.gs └── package.json package.jsonの編集 それぞれのprojectディレクトリのpackage.jsonについては、デプロイ用のスクリプトとしてclasp pushコマンドを定義します。 "scripts": { "deploy": "clasp push" } また、ルートディレクトリにあるpackage.jsonには、プロジェクトごとのデプロイ開始スクリプトを定義します。また、GASプロジェクトの画面を開くためのスクリプトも定義しておくと便利です。 "scripts": { "deploy:project1": "cd project1 && npm run deploy", "deploy:project2": "cd project2 && npm run deploy", "open:project1": "cd project1 && clasp open", "open:project2": "cd project2 && clasp open" }, 設定ファイルの編集 それぞれのprojectディレクトリの設定ファイルについて、appsscript.json(マニュフェストファイル)を編集して、timeZoneを変更しておきます。 { - "timeZone": "America/New_York", + "timeZone": "Asia/Tokyo", "dependencies": { }, "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8" } (参考) 設定ファイルのドキュメント 各設定ファイルのパラメータについては、公式ドキュメントを参照してください。 マニフェストの構造  |  Apps Script  |  Google for Developers GitHub – google/clasp: Command Line Apps Script Projects TypeScriptへの書き換え 次は既存のGASファイルの書き換えです。GitHub Copilot Chat や Cursorなどを用いると、比較的楽にGASファイルをTypeScriptに変換できます。 なお、今回はCursorのComposer機能を使用したため、tsconfig.jsonや、必要なディレクトリなどが自動生成されて便利でした。 CursorエディタやComposer機能の基本的な使い方については、2024年10月に公開されたこちらの記事で詳しく解説していますので、併せてご覧ください。 CursorのComposer機能でAIに0からテストコードを作成してもらう こんにちは、AGESTのバックエンドエンジニアのまさです。今回は、CursorエディタのComposer機能を用いて、AIにテストコードを記述してもらう方法をご紹介します。テストコードはソフトウェアの品質を高めるために重要ですが、手作業で書くのは時間がかかるものです。...  続きを読む  Sqripts 関連記事|Sqripts 変換後のファイル // main.ts declare const saveDrive: (message: JsonData) => void; export interface JsonData { [key: string]: { number: any; app: any; }; } // JSON生成処理 export function generateJson(): JsonData { // スプレッドシートのデータを取得する const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_sheet"); if (!sheet) { throw new Error("Sheet not found"); } const data = sheet.getDataRange().getValues(); // JSONを格納するオブジェクトを作成する const json: JsonData = {}; // シートの各行を処理する for (let i = 0; i < data.length; i++) { json[`app_PJ1_${i}`] = { number: data[i][0], app: data[i][1] }; } return json; } // メイン関数 export function main(): void { saveDrive(generateJson()); } // drive.ts import { JsonData } from './main'; // Google Driveにファイルを保存 function saveDrive(message: JsonData): void { // Google Driveの特定のフォルダにファイルを作成 const folderId = PropertiesService.getScriptProperties().getProperty( "DRIVE_FILE_PATH_PJ1" ); if (!folderId) { throw new Error("Folder ID not found in script properties"); } const folder = DriveApp.getFolderById(folderId); folder.createFile( "sample.json", JSON.stringify(message), MimeType.PLAIN_TEXT ); } // グローバルスコープに公開(globalの代わりにthisを使用) // @ts-ignore this.saveDrive = saveDrive; 書き換え後のディレクトリ構成 変換後のディレクトリ構成は以下のようになります。元の.gsファイルはpushする必要がないため削除します。 . ├── node_modules ├── README.md ├── package-lock.json ├── package.json ├── project1 │ ├── .clasp.json │ ├── appsscript.json │ ├── functions │ │ ├── drive.ts │ │ └── main.ts │ └── package.json ├── project2 │ ├── .clasp.json │ ├── appsscript.json │ ├── functions │ │ ├── drive.ts │ │ └── main.ts │ └── package.json └── tsconfig.json プロジェクトへのデプロイ 定義したスクリプトを使用してデプロイを行います。 $ npm run deploy:project1 Debugger attached. > gas-management@1.0.0 deploy:project1 > cd project1 && npm run deploy Debugger attached. > gas-management-project1@1.0.0 deploy > clasp push Debugger attached. (node:45633) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead. (Use `node --trace-deprecation ...` to show where the warning was created) └─ appsscript.json └─ functions/drive.ts └─ functions/main.ts Pushed 3 files. Waiting for the debugger to disconnect... Waiting for the debugger to disconnect... Waiting for the debugger to disconnect... デプロイが完了したら、GASのプロジェクト画面を開き、main関数を手動で実行して動作確認を行います。GASのプロジェクト画面で「実行」ボタンを押し、関数を選択することで実行できます。 $ npm run open:project1 Debugger attached. > gas-management@1.0.0 open:project1 > cd project1 && clasp open Debugger attached. Opening script: <https://script.google.com/d/◯◯◯◯> Waiting for the debugger to disconnect... Waiting for the debugger to disconnect... 動作確認 初回実行時や権限を変更した場合など、データへのアクセス権限の承認が必要になる場合があります。 おわりに 今回は、GAS開発を効率化するためのツール「clasp」の導入から、実際のGASファイルのTypeScriptへの書き換え、そしてデプロイまでを解説しました。 この記事が、GAS開発をより快適に、そして効率的にする一助となれば幸いです。ぜひclaspを活用して、より良いGAS開発体験を実現してください。 The post clasp導入で既存のGAS開発を効率化!手順とメリットを徹底解説 first appeared on Sqripts .
アバター
この連載では、ソフトウェア開発のQAエンジニアとして働き始めた皆様に向けて、私の実体験をもとに「こんなことを知っておけばよかった」という、ちょっとした気づきを共有します。 一緒にソフトウェア開発のQAエンジニアとしての充実したエンジニアライフを築くためのヒントを探っていきましょう。 <QAエンジニアのスタートガイド 記事一覧> ※クリックで開きます 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- 【第4回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -後編- 【第5回】コミュニケーションが鍵を握る ソフトウェア開発は、一般的に、多くの専門家からなるチームによって行なわれます。 また、ソフトウェア開発は創造的であり、高度で知的な作業が伴うため、チームワークや人間性への配慮は、生産性や品質を含むさまざまな結果に影響を与えます。 チームワークや人間性への配慮に重要なファクターとなるのは「ソフトスキル」です。 ソフトスキルはQAエンジニアにとっても、より一層重要になります。 QAエンジニアの仕事で特に重要なのは「情報提供」であると考えます。そして、伝え方やマインド次第でチームを守ることもできますし、壊すこともできてしまいます。 本記事ではQAエンジニアにとって重要なソフトスキルについて解説します。 チームで働く チームの一員として働くということ QAは多くの場合、1人で価値を届けることはできません。テストを始めとして、誰かが作ったものに対してQAとして貢献することが一般的なありかたではないでしょうか。 つまり、QAはチームを必要としています。 ここで紹介したい品質モデルがあります。JIS X 25010:2013では、利用時の品質の他にも外部特徴・内部特徴・プロセス品質という考え方で整理しています。 利用時の品質にフォーカスするQAは多いと思いますが、プロセス品質もまた重要だと私は考えています。 プロセス品質を大事にしてこそ、良いプロダクトが作れるという考えを私は支持しています。 ソフトウェア開発において、「プロセス」は、ただ単に仕事の受け渡しだけではなく、人のモチベーションやコミュニケーションも含めて考えたほうがよいでしょう。 QAはタスクの受け渡しをするのでなく、チームの一員としてオーナーシップを持ち、プロセス品質にも着目して活動をすることが大切だと考えています。 チームでソフトウェア開発をすることに言及している記事は多くありますが、私は「チーム・ジャーニー」という本をおすすめします。 ■ チーム・ジャーニー:TEAM JOURNEY 〜ゼロの状態から最強のチームをつくりあげるまで〜 (市谷 聡啓 著/翔泳社) 弱さを抱擁できることがQAの強みである ソフトウェアテストでは、ソフトウェアの故障を見つけたり、欠陥を指摘するということがあると思います。 だからといって、QAは喜びすぎたり、ましてや開発者を非難するような振る舞いをしていてはいけないと思っています。 昔、「こんな悪いコードを書いたのは誰だ」や「なんでこんなバグを作るんだ」というような発言をするQAに出会ったことがあります。 私はそれを大変残念だと思いました。 QAは、プロダクトを通じてプロセスの課題や人の弱点を垣間見ることがあります。 だからこそ、QAは優しい存在になる必要があります。 QAは、礼儀正しく、接しやすく、そして何よりメンバーの弱さを受容するような態度が必要だと思っています。 もちろん、チーム開発にとってそういう行動が好ましいという側面があります。 それだけでなく、これらはQAの倫理として守るべきものではないでしょうか。 欠陥を探して故障を見つけるということは大事なことです。 一方で、そういった立場を使って優位に立とうとしたり、人を貶めるようなことは決してしてはいけません。 弱さを抱擁できることこそが、QAの強さであると私は考えています。 「弱さを抱擁する」というフレーズについては西康晴先生の以下の動画から引用しています。 この動画はQAエンジニアにとってあるべき姿について深い洞察が得られるので、ぜひご覧いただきたいです。 コミュニケーションの方法 コミュニケーションの方法としてさまざまありますが、QAのあるべき姿が試される場面として、3つ紹介します。 ミーティング ミーティングはチーム開発においては避けられない活動であり、とても重要です。 ミーティングの効果、生産性の議論はエンジニアリングの分野に限らず活発的です。 ここでは、QAの専門性を発揮できる参加の方法を提案したいです。 「俯瞰的に見る」ということ、「目的志向に立ち返る」ということです。 テスト設計をしていて、抽象と具体を行き来することは少なくないと思います。 QAはミーティングのなかで、「どういう議論をしているのか」「何を話しているのか」を俯瞰で見て、時に抽象でまとめ、時に具体によって前に進めることができます。 あるいは、ミーティングの中で目的を見失ってしまうことがあるかもしれません。 そのなかでもQAは、専門性である「目的志向」で、「目的は何なのか」という問いを立てることができます。 ミーティングを通して、チームのプロセス品質を良くしていくことも、QAとして重要な役割だと考えています。 バグチケット バグチケットを通して開発者にフィードバックすることがよくあると思います。 そのなかでも重要なことは、事実を正確に書く、そして礼儀正しく書くということです。 バグチケットは開発者を批難する手段ではありません。バグチケットはあくまで事実を提示して、チームにとってより良い意思決定を促すために使うものです。 レビュー レビューでもQAの専門性が発揮されると考えます。 レビューはソフトウェア開発でも重要な役割を持っています。一方、体系的に導入している組織は少ないのではないかと考えています。 レビューはリーディング技法などがある一方で、コミュニケーションもまた重要です。 たとえばJSTQB FLでは、レビューのミーティングについて、体系的な解説がされています。 レビューのプロフェッショナルとして、必要に応じて体系化された技術を実装していくことが、QAには求められていると考えます。 コミュニケーションで大切にしてほしいHRT コミュニケーションは会話や発信であると捉えている人は多いと思います。 一方で、私は自分自身のマインドもまた重要だと思います。 ここでは「Team Geek」という書籍で紹介されている、HRTという考え方を紹介します。 ■ Team Geek (Brian W. Fitzpatrick、Ben Collins-Sussman 著、角 征典 訳/O’Reilly Japan) HRTとは、Humility(謙虚さ)、Respect(尊敬)、Trust(信頼)の3つの単語の頭文字を取ったものです。ソーシャルスキルの三本柱であり、人間関係を円滑にするだけでなく、健全な対話とコラボレーションの基盤になると考えられています。 Humility(謙虚) 自分の考えは、絶対に正しいわけではなく、自分自身もまた欠点を抱えていることを理解することです。同時に常に自分を改善していくことも大切です。 他者に対して謙虚であることも重要ですが、一方で自分に対して謙虚であることも重要です。 例えば、「自分の成果物は完璧な状態で見せなければならない」と思っていれば、それは自分自身を完璧だと思いたいことの裏返しであり、謙虚さを失っていると言えます。 時には不完全な成果物を見せることも必要だと知ることが大切です。自分は完全無欠ではないということを理解して、自分の成果物もまた不完全であることを受容することが必要なのです。 Respect(尊敬) 一緒に働く人の人格や能力を尊重し、心から思いやることです。相手は「開発者さん」といった役割ではなく、人格のある人間であることを認識することでもあります。 特にQAは批判を行うことがあります。 そうした中で成果に対する建設的な批判と性格に対する攻撃的な批難を区別して理解する必要があります。 建設的な批判は、心から他人を思いやり、成果を改善してほしいと願っていないと生まれません。そして、そこに尊敬が含まれていることが重要なのです。 Trust(信頼) 自分以外の人は有能であり、正しいことをすると信頼することです。 チームのメンバーはそれぞれ何かしらの専門家であり、自分とチームに対して恩恵をもたらしてくれていると心から信頼しましょう。 これは批判を受ける際にも重要となります。 仕事の中で批判されているのは成果物であり、自分自身ではないということを理解することが大切です。 また、 批判する対象は作成者ではなく成果物であるべき ということを肝に銘じておく必要があると考えます。 おわりに 優れたQAエンジニアは、技術的なスキルだけでなく、コミュニケーション能力も高いものです。 チームの一員としての自覚を持ち、HRT(謙虚さ、尊敬、信頼)を念頭に置いて行動することで、QAエンジニアはチームに貢献し、プロジェクトを成功に導くことができます。 コミュニケーション能力は、一朝一夕で身につくものではありませんが、意識して継続的に努力することで、より良いチームとより良い製品を作ることができると信じています。 【連載】QAエンジニアのスタートガイド 記事一覧 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- 【第4回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -後編- 【第5回】コミュニケーションが鍵を握る The post 【第5回】コミュニケーションが鍵を握る|QAエンジニアのスタートガイド first appeared on Sqripts .
アバター
こんにちは、QAのゆーすけです。 私は今でこそソフトウェアテスト会社の一員として日々努めていますが、元々はゲームテストがメインの会社のメンバーでした。 ゲームテストの会社自体はコンシューマーゲーム→PC→携帯(FP/スマホ)とテストを渡り歩いてきましたが、元々はガチガチのゲーム好きからゲームデバッグに応募した経歴になります。 今はゲームテストに関わることが全くないですが、元々のゲーム好きの興味として最近JSTQB ※1 のゲームテストシラバスを眺める時間を設けるようにしています。 ※1 JSTQB認定テスト技術者資格 日本におけるソフトウェアテスト技術認定資格運営組織。ISTQBの加盟組織でもあるので、その資格および教育は国際的にも有効 ゲームテストの思い出 私がゲームテストを主戦場としていたことは、ゲーム機がネットワークに繋がるといったことはほぼなく(PlayStation 2では別売のBBユニットが必要な時代……)、 ゲームの重篤な不具合=回収、リマスターの販売 といったことが当たり前でした。 ※担当案件でリマスター版が出たことが一度だけあります(広い意味なら2回ですが) ※PlayStationの某大型RPGの進行不能不具合は新聞にまで載った最も?有名な不具合だと思います。  直すためにはメモリーカード(PS)の発送、修復が必要  この不具合は今の市場流通版(アーカイブス版)でも修正されていない また、発売日というものが明確に決められるので、その発売日何カ月前には開発・テストが収束し、製品を量産(カートリッジもしくはROM)し、出荷して、流通させる、というスケジュールが必須でした(これは多分今もそう)。 ※とあるメーカー、とあるゲームタイトルのキックオフで 「すでに発売日を決めて広告をxxxxx円かけて大体的に行っているので、  くれぐれも発売遅延がないように品質管理を徹底してください」 と言われたのは今ではとてもいい思い出。ネタになってます(ちゃんと当初の予定日に発売しました)。 ゲーム特有の観点として 閑話休題、 JSTQBのゲームテストシラバスに以下のような文章が記載されています。 ブラックボックステスト技法(black-box test technique)を使ったテストでは、プラットフォームによる 違いはほとんどない。しかし、各ゲーム機メーカーは、ビデオゲームが公開される前に準拠しなければならない独自の要件を定めている場合がある。これらの要件は、秘密保持契約に基づいて開発者やパブリッシャーに提供される独自の文書である。各要件のチェックリストはいくつかのカテゴリーで構成されており、ゲーム機メーカーに拒否されないためには、ゲームソフトウェアはそれらに準拠しなければ ならない ゲームテストシラバスより抜粋 PC・webサービス系のテストを行っていると意識することがないですが、 ゲーム業界のような3rdパーティーがいるものでは、一般のテストと同様もしくはそれ以上に強く意識しなければならないのが上記のようないわゆる「作成基準」というものになります。 ※1stパーティーがプラットフォーマー(任天堂、ソニー、マイクロソフトなど)   2ndパーティーがユーザーとして、   3rdパーティーはゲーム開発企業と言われています。 つまり、ゲームとしての品質がどんなに高水準であっても、メーカー側の作成基準に抵触事項が1件でも存在した場合はリジェクトを受けてしまうわけです。 前述した広告費をかけた、とプレッシャーをかけていただいたプロジェクトでも、機能部分の重篤な不具合よりも、作成基準を通過できるか、という点の方が気になって胃がキリキリとしたものです。 この各種作成基準はひとつひとつを詳細に覚えておく必要まではありませんが、品質基準、観点、方針として心に留めておくと有益なものばかりなので、思い出話を含めて軽く紹介していきたいと思います。 作成基準例 正しい用語を使う 何を当たり前のことを、と思われるかもしれませんが、意識しないと正しい用語を使うことは結構難しかったりします。 「取り扱い説明書を見て、playstation2のコントローラーで十字ボタンのことを調べた」 昔の知識に偏っていて申し訳ないですが、 上記のような文章がゲーム中にあると、即再生基準でリジェクトを受けること間違いなしです。 正しくは  ・  ・  ・ 「解説書を見て、”PlayStation🄬2”のコントローラで方向キーのことを調べた」 となります。 複数のプラットフォームがある場合、それぞれで使用される用語は差別化されていることが多いので、自分の使っている言葉がその環境において本当に適切なものであるか、ということは非常に大事な要素です。 こういったことは作成基準など関係なく、普段の日常やビジネス上の会話や、論文、レポート作成でもかなり有効になる意識となります。 中断再開、復元を意識する とあるハードの作成基準では、 「ディスクトレイの開閉を行った後でも適切にゲームに復帰できること」 というものがあります(今もあるかもしれませんが)。 流石にPC・webサービス系のテストでは上記のような開閉を直接的に使うことはないかもしれませんが、携帯電話系のテストでは 携帯(フィーチャーフォン)の開閉を行っても正しく動作が復帰すること (いわゆるサスペンド/レジュームの観点) Androd端末において、端末デバイス側にバックキーが搭載されている場合、デバイス側からのインプットを受けて画面遷移を行った場合でも、適切な動作を保つこと などが派生観点としてあげられるかと思います。 画面端に重要な情報の表示、描画を行わない 重要情報の見逃しによる不利益防止のための観点になりますが、こういった内容もUI/UXなどの観点から意識できるとよりよい製品、品質構築に寄与できる観点だと思います。 このチェックを漏れなく行うために、液晶ディスプレイ上に透明テープを貼っている人をみたことは今でも忘れられない衝撃として記憶に残っています。 過剰の演出、画面描写を行わない これは1997年に某テレビ番組で起こった光過敏性発作が有名だと思いますが、いわゆる激しい画面の明滅を禁止する、という内容です。 こういったその時々に起こった事象なのが制約・規約として盛り込まれるということもあります。 また仮に明記された制約がなかったとしても、現在および過去の事象と照らし合わせて問題だと思われることを指摘していくことも、品質観点からは重要な活動になりますので、品管に携わる人達には幅広く、そして深い知識が求められることになります。 まとめ 今現在、元々ゲームデバッグからキャリアの始まった自分が、今こうしてソフトウェアテストに携わって少なからず活躍できている?ことを考えると、何のデバイスにどう関わってきたかはそこまで重要ではないのかもしれません。 品質的な考え方は別分野別デバイスでも有益だということが分かりますし、より大事なのは関わったものを柔軟に適用し、様々な知識を多角的に広く深く吸収し続ける、ということなのかもしれませんね。 The post ゲームテストから考える品質管理に大事なこと first appeared on Sqripts .
アバター
帰納的な推論 と 発見的な推論(アブダクション) は、 私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。 それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意すると質の高い思考ができるのか、基本知識を押さえておくと実務のレベルアップにつながります。 <実務三年目からの発見力と仮説力 記事一覧> ※クリックで開きます 【第1回】見つけるための論理【連載初回、全文公開中】 【第2回】 “共通項”を見つけ出す 【第3回】発見はよい観察とよい方法から 今回は帰納的推論で「発見」をするために参考になる方法(見方考え方)を紹介します。 再現・枚挙的帰納 第2回で紹介した枚挙的帰納の例(A)、(B)(第2回の図2-3を図3-1として再掲)、それぞれでどんな風に推論しているか、コニャン君の脳内を覗いてみましょう。 図3-1 枚挙的帰納の例 【注意】 以下に再現する“推論の筋道”は、「こういう形/流れもある」を示すもので、誰でも・どんな場合でもこのような流れを辿る、と主張するものではありません。 (A)の形の場合 図3-1 (A)、コニャン君の思考の筋道は図3-2のようになるでしょう。 図3-1 コニャン君の脳内(A) こうした思考を支えるのが、前回解説した 自然の斉一性 や 因果性 という概念でした。 【第2回】 “共通項”を見つけ出す|実務三年目からの発見力と仮説力 帰納的な推論 と 発見的な推論(アブダクション) は、私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意す...  続きを読む  Sqripts 関連記事|Sqripts プログラム(ソースコード)に混入する欠陥は自然現象ではありませんが、筆者の経験によれば、斉一性に似たような状況が生じることがあります。 ある箇所のある処理で生じたエラー(誤り。勘違い、思い込み、考慮不足、仕様の誤読、etc.)は、他の似たような箇所での同じような処理でも生じがち。 ソースコードのコピペも欠陥を伝播しがち。 複数の箇所から呼び出されるモジュールに欠陥があると、特定の条件を満たしたら同じような故障が各地で発生することが起こりがち。 【訂正】この(A)、 第2回 では「共通項Pを見つける」例と述べましたが、「特殊文字を入力すると(共通項P)、フリーズする(共通項Q)」形と言えますね。間違えました。 (B)の形の場合 (B)は、共通項Pだけでなく共通項Qも見つけ、両者の関係性を見つけるのに、ちょっと“手数”がかかるでしょう。 (図3-3。図3-1との対応の参考として、吹き出し中に丸数字をつけています) 図3-3 コニャン君の脳内 (B) 発見=観察+推論の方法 「実験的探究の4方法」 図3-1 (A)(B)のような推論の方法は、何といっても 観察 ――起こっている事実を見落とさず、適切な詳しさで見る―― に支えられています。 ( 観察 については後ほど触れます) そして、よい 観察 に基づいて“共通項”(中でも 因果関係 )を見つけるための方法を、19世紀イギリスのJ.S.ミルという哲学者が考えました。 自身の著作の中では「実験的探究の4方法」と題されていますが、「ミルの帰納法」「ミルの方法」などとして知られます。 (解説している方法は5つだが、ひとつは2方法の組合せ) 一致法 差異法 一致差異併用法 剰余法 共変法 本記事では、「ソフトウェアの動作確認やテストで、故障や不具合に遭遇した局面」や「デバッグ中に原因を探る局面」を想定して、結果から原因を探る場合に焦点を当てて説明します。 以降の解説では、 前件(先行する事象群): 故障や不具合の発生に先立つ 環境・設定、データ、状態、コード中のロジック、入力・操作、など を指します。 後件(後続する事象群): ソフトウェアの実行が引き起こす 出力・表示、状態(の変化)、データの変化、など(故障や不具合自身を含む) を指します。 (前件や後件の)要素: 前件や後件中の互いに識別可能なものごとを指します。 J.S.ミルの帰納法 一致法:多くの事例の「共通点」に着目する 着目する事象a(ソフトウェアの故障や不具合など)を生じる事例をふたつ以上集める。 ①前件の中に全事例で共通する要素がひとつだけある(要素Aとする)。 ②要素Aだけが全事例で一致している。 ③要素A以外の前件の要素が異なると、事象a以外の後件は異なる。 ①②③が共に満たされるなら、その要素Aが着目する事象aの原因(または、原因の不可欠の一部分)である、と考えることができます。 図3-4 一致法の概略 【特徴】 「ある要素がなくても着目する事象が生じるなら、その要素は原因から取り除いて考えてよい」という考え方に基づく( 消去法 )。 着目する事象を含む事例をいくつか集めれば適用できる。 「特定の要素を取り除いて結果を見る」といった実験ができない場合に適している。 後述の差異法の前段階として原因の候補を絞るのに適している。 【注意点】 事例は「前件では要素Aだけが共通、後件では事象aだけが共通している」こと。 他の要素や事象が共通していると、因果関係が絞り切れない。 (別の方法の適用などにより、さらに絞り込むことが必要) 事例は多いのが望ましい。 (少ないと、原因の絞り込みができなかったり、偶然の結果を原因と間違えたりするおそれが大きい) 前件の要素Aと事象aがともに、隠れた他の原因から生じている場合( 結果の共存 )を識別できない。 事象aが、前件の要素A ではない 原因による場合を識別できない。 事象aが多数の原因の複合により生じている場合、先行事象Aがどのように関与しているかは判らない。 図3-4a 一致法の例 差異法:異なる結果を生む「違い」に着目する 着目する事象aを生じる事例( 積極事例 )と、生じない事例( 消極事例 )を集める(最低、各ひとつずつ)。 ①前件に特定の要素Aがあると、事象aが生じる。 ②前件に特定の要素Aがないと、事象aは生じない。 ③それ以外は、前件と後件は全く同じ。 ①②③が共に満たされるなら、要素Aが事象aの原因(または、原因の不可欠の一部分)である、と考えることができます。 図3-5 差異法の概略 【特徴】 「ある特定の要素を除くと着目する事象が生じないなら、その要素は原因と考えてよい」という考え方に基づく(これも 消去法 )。 積極事例、消極事例それぞれひとつずつあれば適用できる。 別の方法で推定された因果関係を確認するのに適している。 (事象の発生原因がある程度推定できている状況で適用するのがよい) 一致法では識別できない「事象aが、前件の要素A ではない 原因による」場合を誤認しない。 【注意点】 条件を満たす事例を集める手間がかかる。困難な場合もある。 「特定の要素を取り除いて結果を見る」といった実験ができない場合には適さない。 原因の特定に適用する際には注意が必要。 (発生原因の推測がないと、ブルート・フォース的に手当り次第に試すことになる) 図3-5a 差異法の例 一致差異併用法:ふたつの方法の合わせ技 着目する事象aが生じる事例( 積極事例 )を2つ以上、 生じない事例( 消極事例 )を2つ以上、それぞれ集める。 ①積極事例では、先行する要素Aと後続の事象aが含まれて いることだけが共通 している。 ②消極事例では、先行する要素Aと後続の事象aがともに含まれて いないことだけが共通 している。 ①②が共に満たされるなら、要素Aが事象aの原因(または、原因の不可欠の一部)である、と考えることができます。 (消極事例の前件は、積極事例のそれと同じか類似していると対比が明確になる) 図3-6 一致差異併用法の概略 図3-1(B)、図3-3「ソフトウェアXはソフトウェアZがプリインストールされている機種で故障Fを起こす」は、この考え方を用いているわけですね。 図3-3 の②’で、「他の点で、起こる機種と起こらない機種に共通項はない」ところから、「故障Fが起こる場合と起こらない場合の違い」が絞り込まれます。 (他にも共通項がある場合は、さらに絞り込みを行なうことになるでしょう) 【特徴】 差異法だけでは「A : a」の組を見つけられないような場合でも使える。 事象が起こる場合(積極事例)、起こらない場合(消極事例)の共通点と相違点を広く見渡して検討できる。 【注意点】 積極事例と消極事例を集める手間がかかる。 図3-6a 一致差異併用法の例 剰余法:既知の関係との差分に着目する 着目する事象が生じる事例を取り上げる。 ①事例の一部の事象は、既に前件と後件の関係(因果関係)が判っているとする。 ②事例の前件・後件から、既知の前件・後件の組(①)を全て取り除く。 ②で残った前件・後件の組は、それぞれ前件(原因)と後件(結果)と考えることができます。 図3-7 剰余法の概略 【特徴】 差異法のバリエーションと言える。 既知の因果関係を用いて原因探求の省力化が期待できる。 この方法を適用すると、次のような事態に遭遇することがあります。 ある事例がある(例:A, B : a, b, c)。 このうち、A : a, B : b は既知の因果関係である。 そこでこれらを取り除いたら、「nil : c」になる!? (注:nil=空のこと、つまり前件が空) これは、a, b, cという後件に対して、候補として考えたA, Bの他に前件がある可能性を示唆しています。 こうした事態になったら、 前件の見落とし・見逃し がないか確かめるか、 隠れた前件 の存在を仮定して要素Cを探すか、といった方向に向かうことになるでしょう。 (この例は、決して「前件の要素と後件の要素は1対1対応でなければならない」ということ ではありません ) 【注意点】 この方法で残った前件の要素が後件で残った事象の原因かどうかは、別途確かめる必要がある (差異法ほど強い蓋然性を示してはいない)。 前件の要素が複数残った場合(例:BとC)、BとCのどちら(または両方とも)が原因なのかは、この方法だけでは判らない。 【特徴】で述べた「既知の前件:後件を取り除くと、“前件が空になる”事態が生じ得る」は、注意点でもある。 図3-7a 剰余法の例 共変法:特定要素の変化に着目する 着目する事象を生じる事例を取り上げる。 前件の特定の要素だけを変化させて(値、数量、設定、etc.)、後件の変化を見る。 着目する事象aの変化を引き起こす特定の要素Aがあったら、それが事象aの原因(または、事象aと何かしらの因果関係によるつながりがある)と考えられます。 図3-8 共変法の概略 【特徴】 前件の特定の要素の 有無 ではなく、要素の 変化 (値、数量、設定、etc.)に着目した方法。 一致法、差異法、剰余法といった、消去法に基づく方法が適用できない/しづらい場合に、特定の要素を変化させて原因と結果の関係を推定する役に立つ。 他の方法が使える場合でも、因果関係が推定された後に「原因と考えられる要素Aの変化が結果と考えられる事象aにどんな影響を与えるか」を調べる役に立つ。 【注意点】 この方法だけでは、要素と事象の因果関係が確かめられない場合がある。 (前件の要素Aの変化が別の要素や事象を通してaに影響を与えている場合など) 前件の要素Aを変化させた時に、後件に何の変化も見られないからといって、要素Aが結果にまったく影響を与えていないとは言えない。 図3-8a 共変法の例 気をつけたい点 筆者自身のデバッグ経験・テスト経験を振り返ると、一致差異併用法、剰余法、共変法が活躍した記憶があります。 特定の要素だけを変化させたり、特定の要素の有無だけ変えたりという実験的な操作は、ソフトウェアの場合は比較的行ないやすいからでしょうか。 ミルの方法は起こった事象からその原因を見つけようとする際のガイドとして大いに参考になるものと思いますが、適用に当たって気をつけたい点がいくつかあります。 5つ(4つ)の方法、どれかひとつで原因を突き止められるとは限りません。 いくつかの方法を組み合わせて使うことも考えましょう。 いずれの方法も結論を導いた段階では蓋然的に正しいと言えるにとどまります。 結論を基にさらに調べる、原因から結果への演繹的な説明を考える、 などの作業が必要です。 また、方法は推論を補強はしますが、保証はしません。 「○○法を使っているから正しい推論であり、結論も正しいんだ」といった考えに囚われないようにしましょう。 発見を支えるのは観察(と、仮説) ミルの方法を活かすには・観察が大切 冒頭で触れたように、帰納的推論による発見を支えるのは“ 観察 ”(と、その補助として 事実の収集、記録(記憶) )です。 前件(先行する事象群)や後件(後続する事象等)として取り上げる事項の 焦点を絞る 。 (すべてを見ようとするのはかえって見落としを招きやすい) 故障や不具合の内容に応じて、操作や入力、ソフトウェアの環境やデータ、ハードウェア環境、etc.。 生じた故障は動作か、データの変化か、状態異常か、外部への出力か、etc.。 同じく、 粒度感 にも気をつける。 大まかな原因を把握するなら、故障は概要レベルで捉え、前件や後件は大づかみに区別する、 因果関係の詳細を突き止めようとするなら、故障を詳細に記述し、前件や後件は詳細に区別する、etc.。 調べて見込みがなかったら、「調べ方や調べるところを変えよう」という判断も必要。 ミルの方法を活かすには・もう一点 帰納的推論による発見を支えるものには、「着目した事象にまつわる因果関係を調べるに当たり、ある程度推測を立てる」という態度もあります。 一般に、起こった事象(故障や不具合) だけ から何が原因(の候補)か当たりをつけるのは困難で、 「こういうことが原因となっているのではないか」といった推測が必要になります。 これも誰しもやっていることでおかしなことではありません。 この推測( 説明仮説 )が原因探求の道標になります。 「なんとなく・当てもなく原因を探す」のではなくて、「ある仮定に基づいた推測に沿っている」ことを意識しましょう。 (ソフトウェアの場合、仕様や設計やソースコードに基づけば推測しやすいですが、「思いがけない遠く離れた箇所の仕様/設計/実装」が影響を及ぼす場合や、外部環境要因が干渉する場合もありますし、仕様や設計が当てにならないことも……) 説明仮説に関わる推論は、アブダクションの回で取り上げます。第5回以降をお楽しみに。 ★ 次回は帰納的推論にもある“落とし穴”を紹介する予定です! 参考文献 近藤洋逸, 好並英司 『論理学入門』 岩波書店 1979 鈴木美佐子 『論理的思考の技法Ⅱ』 法学書院 2008 藤野登 『論理学 伝統的形式論理学』 内田老鶴圃 1968 J.S.ミル(著), 大関将一(訳) 『論理学体系 : 論証と帰納 3』 春秋社 1958 米盛裕二 『アブダクション 仮説と発見の論理』 勁草書房 2007 図版に使用した画像の出典 Loose Drawing 人物画をお借りしています。 品質探偵コニャン:Produced by Sqripts . No Unauthorized Reproduction. 【連載】ソフトウェアエンジニアのための論理スキル[実務三年目からの発見力と仮説力] 記事一覧 【第1回】見つけるための論理 【連載初回、全文公開中】 【第2回】 “共通項”を見つけ出す 【第3回】発見はよい観察とよい方法から The post 【第3回】発見はよい観察とよい方法から|実務三年目からの発見力と仮説力 first appeared on Sqripts .
アバター
こんにちは、バックエンドエンジニアのまさです。 AI技術の急速な進化に伴い、従来のキーワード検索では対応できない「意味的な類似性」に基づく検索ニーズが急増しています。本記事では、 オープンソースRDBMSであるPostgreSQLにpgvector拡張を組み込むだけで、簡単にベクトル検索システムを構築する方法 を解説します。 ベクトル検索 とは、文章を数値ベクトルに変換して抽象的な意味を検索する技術であり、キーワード依存型の検索では捉えきれない「ユーザーが本当に求めている意図」を、 高い精度 で汲み取れる検索手法です。 この記事では、ベクトル検索をPostgreSQLに組み込む方法を、ハンズオン形式で環境構築を進めながら説明していきます。 ベクトル検索とは 3分で分かるベクトル検索の仕組み 従来のキーワード検索は、文字通りキーワードが一致するかどうかで検索結果を返します。しかし、言葉の表現は多様であり、ユーザーの意図と完全に一致するキーワードが使われるとは限りません。そこで登場するのが ベクトル検索 です。 ベクトル検索は、テキストや画像などのデータを、数値の集まりである ベクトル に変換します。このベクトルは、元のデータの意味的な特徴を捉えており、類似した意味を持つデータは、ベクトル空間上で近い位置に配置されます。 具体的な仕組み: エンベディング:  テキスト(質問や文章)を、事前に学習済みのAIモデル(例:OpenAIのtext-embedding-ada-002)を用いて、数値ベクトルに変換します。この処理をエンベディングと呼びます。 ベクトルデータベース:  エンベディングされたベクトルをデータベース(この例ではPostgreSQL + pgvector)に格納します。 類似度計算:  検索クエリも同様にベクトルに変換し、データベース内のベクトルとの類似度を計算します。類似度の高いベクトルを持つデータが、検索結果として返されます。 例: 「猫が好きな人におすすめの映画は?」という質問をベクトル検索にかけると、「猫」というキーワードが含まれていなくても、「猫が登場する映画」「猫を飼っている人が主人公の映画」など、意味的に関連性の高い映画が検索結果として表示される可能性があります。 つまり、ベクトル検索は、キーワードに縛られず、意味に基づいた柔軟な検索を実現する技術なのです。 PostgreSQL採用の5大メリット ベクトル検索システムを構築する上で、PostgreSQLを採用するメリットは多岐にわたります。以下に主な5つのメリットを挙げます。 拡張性:  pgvector拡張により、PostgreSQLにベクトル検索機能を追加できます。既存のデータベース環境を大きく変更する必要はありません。 コスト効率:  オープンソースであるため、高額なライセンス費用は不要です。必要なハードウェアリソースのみで運用できます。 信頼性:  PostgreSQLは長年の実績を持つ堅牢なRDBMSであり、高い信頼性と安定性を誇ります。 標準SQL対応:  既存のSQLクエリと組み合わせて、複雑な検索処理を記述できます。 コミュニティサポート:  世界中に活発なコミュニティが存在し、豊富な情報やサポートが得られます。 従来検索とのパフォーマンス比較表 検索方式 検索精度 検索速度 (データ量依存) 柔軟性 備考 キーワード検索 キーワード一致に依存。曖昧な表現や同義語に弱い。 高速 低い。キーワードの厳密な一致が必要。 シンプルな検索には適している。 ベクトル検索 意味的な類似性に基づくため、キーワードに依存しない。高い精度を実現。 データ量に依存。インデックス構造で高速化可能。 高い。ユーザーの意図を汲み取った柔軟な検索が可能。 大量のデータに対しては、適切なインデックス設計が重要。 全文検索 キーワード検索より高度な検索が可能だが、意味理解は限定的。 データ量に依存。 中程度。 日本語の形態素解析など、言語依存の処理が必要な場合がある。 補足: パフォーマンスは、データ量、ハードウェア、インデックス設計などに大きく左右されます。 上記比較表はあくまで一般的な傾向を示すものであり、実際のパフォーマンスは環境によって異なります。 専用のベクトルデータベースとの比較 専用のベクトルデータベース(例: Chroma, FAISS, Pinecone)とPostgreSQLの拡張機能であるpgvectorは、それぞれ異なる強みを持っています。ここでは、pgvectorと専用ベクトルデータベースとの違いや、それぞれのメリット・デメリットを解説します。 pgvectorの特徴 pgvectorは、PostgreSQLにベクトル検索機能を追加する拡張機能です。以下が主な特徴です: リレーショナルデータとの統合 :ベクトルデータと従来のリレーショナルデータを同じデータベースで管理可能。 低コスト導入 :既存のPostgreSQL環境に拡張機能として追加するだけで利用可能。 ACID準拠 :トランザクション管理やセキュリティ機能をそのまま利用可能。 専用ベクトルデータベースの特徴 専用ベクトルデータベース(例: Chroma, FAISS, Pinecone)は、ベクトル検索に特化した設計がされています。以下が主な特徴です: 高速検索 :高次元ベクトルに最適化されたインデックス設計(例: HNSW, IVF)。 スケーラビリティ :分散システムによる水平スケーリングが容易。 多様なデータ形式対応 :画像、音声、動画などの非構造化データも効率的に処理可能。 比較表 項目 pgvector 専用ベクトルデータベース(例: Chroma, FAISS) 導入コスト 低い(既存PostgreSQL環境で利用可能) 高い(新規インフラ構築が必要) 速度(大規模データ) 中程度(PostgreSQL依存) 高速(専用設計による最適化) スケーラビリティ 垂直スケール(ハードウェア増強が必要) 水平スケール(分散システム対応) 統合性 高い(SQLクエリでリレーショナルデータと統合) 低い(別途APIやミドルウェアが必要) ユースケース 小〜中規模データ、既存RDBMSとの統合 大規模データ、高速検索が求められるAI/MLワークフロー 学習コスト 低い(PostgreSQLユーザーに馴染みやすい) 中〜高(新しいツールやAPIの習得が必要) pgvectorのメリットとデメリット メリット 簡単な導入手順 :PostgreSQL環境に拡張機能としてインストールするだけで利用可能。 低コスト運用 :既存インフラを活用できるため、新たなサーバー構築が不要。 SQL統合性 :従来のSQLクエリと組み合わせてハイブリッド検索が可能。 デメリット パフォーマンス限界 :大規模データセットや超高次元ベクトルでは専用VectorDBに劣る。 水平スケーリング非対応 :PostgreSQL自体が分散システムに最適化されていないため、大量トラフィックには不向き。 機能制約 :画像や音声など非構造化データへの対応は限定的。 専用ベクトルデータベースのメリットとデメリット メリット 高速な類似検索 :HNSWやIVFなど、高度なインデックスアルゴリズムを採用。 大規模データ対応 :分散システムによる水平スケーリングで数十億件以上のベクトル処理も可能。 柔軟性 :画像、音声、動画など多様なデータ形式に対応。 デメリット 導入・運用コストが高い :新たなインフラ構築や運用管理が必要。 学習コストが高い :新しいツールやAPIの習得が求められる。 統合性が低い :従来のRDBMSとの連携には追加開発が必要。 選択基準 pgvectorを選ぶべきケース 既存のPostgreSQL環境を活用したい場合 中小規模のプロジェクトでコスト効率を重視する場合 リレーショナルデータとの統合性が重要な場合 専用VectorDBを選ぶべきケース 数千万〜数億件以上の大規模ベクトル検索を行う場合 非構造化データ(例: 画像、音声)の処理が必要な場合 高速性とスケーラビリティを最優先する場合 pgvectorは、PostgreSQLユーザーにとって手軽かつコスト効率の良い選択肢であり、中小規模プロジェクトには最適です。一方、専用VectorDBは、大規模かつ複雑なAI/MLワークフローにおいて圧倒的なパフォーマンスを発揮します。用途や要件に応じて、それぞれの特性を活かした選択を行うことが重要です。 環境構築 本章ではハンズオン形式で PostgreSQLコンテナのセットアップ から、 Streamlitを用いたフロントエンドの構築 、そしてそれらを連携させる Docker環境の設定 まで、必要な手順をわかりやすく解説します。この章の手順に従うことで、pgvectorを用いた簡単なベクトル検索システムを構築できます。 環境構成 上記のように非常にシンプルな構成をdocker composeで構築します。 ディレクトリ構成は以下のようになります。 ├── .streamlit │ └── secrets.toml *# DB接続情報* ├── docker-compose.yml ├── postgres │ ├── Dockerfile *# PG拡張機能インストール* │ └── initdb │ └── init.sql *# テーブル定義* └── streamlit ├── Dockerfile *# Python環境構築* ├── app.py *# メインアプリ* ├── embeddings.py *# ベクトル生成ロジック* ├── requirements.txt └── seed.py *# テストデータ生成* PostgreSQLコンテナの環境構築 PostgreSQLのデータベースを起動するコンテナ上に初期設定用のSQLファイルを作成します。 CREATE EXTENSION IF NOT EXISTS vector; -- サンプルテーブル作成(必要に応じてカスタマイズ) CREATE TABLE documents ( id SERIAL PRIMARY KEY, title TEXT, content TEXT, embedding VECTOR(1024) ); CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops); Streamlitコンテナの環境構築 メイン処理となるpythonコードを記述したファイルを作成します。 import streamlit as st import pandas as pd import numpy as np from datetime import datetime import psycopg2 from psycopg2.extras import execute_values from sqlalchemy.sql import text from streamlit.logger import get_logger from embedding import Embedding logger = get_logger(__name__) embedding = Embedding() # ページ設定 st.set_page_config( page_title="Vector Database Demo", page_icon="🔍", layout="wide" ) def get_embedding(text): return embedding.get_embedding([text])[0] # データベース接続関数 def get_connection(): return st.connection('postgresql', type='sql') # メインアプリケーション def main(): st.title("📊 Vector Database Demo") # サイドバーでの操作選択 operation = st.sidebar.selectbox( "操作を選択", ["データ表示", "データ追加", "ベクトル検索"] ) if operation == "データ表示": show_data() elif operation == "データ追加": add_data() elif operation == "ベクトル検索": vector_search() def show_data(): st.header("📋 登録データ一覧") conn = get_connection() # データ取得 query = "SELECT id, title,content FROM documents LIMIT 100" df = conn.query(query, ttl=0) if not df.empty: st.dataframe(df) else: st.info("データが登録されていません") def add_data(): st.header("➕ データ追加") # 入力フォーム with st.form("data_form"): title = st.text_input("タイトルを入力") content = st.text_area("テキストを入力") submitted = st.form_submit_button("登録") if submitted and content: conn = get_connection() # サンプルとして、ランダムな1536次元ベクトルを生成 # 実際のアプリケーションでは、適切なエンベッディングモデルを使用する embedding = get_embedding(title + " " + content) # データ登録 query = text(""" INSERT INTO documents (title, content, embedding) VALUES (:title, :content, :embedding) """) params = {"title": title, "content": content, "embedding": embedding} try: with conn.session as session: session.execute(query, params) session.commit() st.success("データを登録しました") except Exception as e: st.error(f"エラーが発生しました: {str(e)}") def vector_search(): st.header("🔍 ベクトル検索") search_text = st.text_input("検索テキストを入力") k = st.slider("表示件数", min_value=1, max_value=10, value=5) if st.button("検索") and search_text: # サンプルとして、ランダムなクエリベクトルを生成 # 実際のアプリケーションでは、入力テキストを適切にエンベッディング query_vector = get_embedding(search_text) conn = get_connection() # コサイン類似度による検索 query = """ SELECT title,content, 1 - (embedding <-> :query_vector) as similarity FROM documents ORDER BY embedding <-> :query_vector LIMIT :k """ params = {"query_vector": str(query_vector), "k": k} try: df = conn.query(query, params=params, ttl=0) if not df.empty: # 結果表示 for _, row in df.iterrows(): with st.expander(f"{row['title']} 類似度: {row['similarity']:.4f}"): st.write(row['content']) else: st.info("検索結果が見つかりませんでした") except Exception as e: st.error(f"検索中にエラーが発生しました: {str(e)}") # アプリケーション実行 if __name__ == "__main__": main() テキストの埋め込み処理を行うpythonコードを記述したファイルを作成します。 今回の例ではデフォルトで埋め込み用のモデルにmultilingual-e5-largeを使用するように設定しています。このモデルを変更することで検索時の傾向等を変えることが可能です。 intfloat/multilingual-e5-large · Hugging Face import torch.nn.functional as F from torch import Tensor from transformers import AutoTokenizer, AutoModel class Embedding: def __init__(self, model_name: str = 'intfloat/multilingual-e5-large'): self.model_name = model_name self.load_model() def load_model(self): self.tokenizer = AutoTokenizer.from_pretrained(self.model_name) self.model = AutoModel.from_pretrained(self.model_name) def average_pool( self, last_hidden_states: Tensor, attention_mask: Tensor ) -> Tensor: last_hidden = last_hidden_states.masked_fill(~attention_mask[..., None].bool(), 0.0) return last_hidden.sum(dim=1) / attention_mask.sum(dim=1)[..., None] def get_embedding(self, input_texts: list[str]) -> list[float]: batch_dict = self.tokenizer(input_texts, max_length=512, padding=True, truncation=True, return_tensors='pt') outputs = self.model(**batch_dict) embeddings = self.average_pool(outputs.last_hidden_state, batch_dict['attention_mask']) return F.normalize(embeddings, p=2, dim=1).tolist() 初期データの投入を行うpythonコードを記述したファイルを作成します。 単純にタイトルと内容をならべ、それらをデータベースに埋め込み表現と共に保存しています。 import psycopg2 import numpy as np from psycopg2.extras import execute_values from embedding import Embedding test_data = [ { "title": "Dockerコンテナのベストプラクティス2025年版", "content": "Dockerコンテナを本番環境で効率的に運用するためのベストプラクティスを解説します。イメージサイズの最適化、セキュリティ対策、ネットワーク設定、ボリューム管理など、実践的なトピックを網羅的にカバーします。マルチステージビルドの活用方法や、環境変数の適切な管理方法についても詳しく説明します。" }, { "title": "PyTorchによる深層学習モデルの最適化手法", "content": "PyTorchを使用した深層学習モデルのパフォーマンス最適化について解説します。バッチサイズの調整、学習率スケジューリング、データローダーの最適化、GPUメモリの効率的な使用方法など、実践的な最適化テクニックを紹介します。" }, { "title": "マイクロサービスアーキテクチャの設計パターン", "content": "マイクロサービスアーキテクチャを採用する際の主要な設計パターンについて解説します。サービス間通信、データ一貫性の確保、障害対策、モニタリング戦略など、実装時の重要なポイントを詳しく説明します。" }, { "title": "Kubernetes運用管理の実践ガイド", "content": "Kubernetesクラスタの効率的な運用管理方法について解説します。リソース管理、オートスケーリング、モニタリング、セキュリティ対策など、実運用で必要となる知識を体系的に説明します。" }, { "title": "効率的なデータベースインデックス設計", "content": "リレーショナルデータベースにおけるインデックス設計のベストプラクティスを解説します。クエリパフォーマンスの最適化、インデックス選択の基準、メンテナンス戦略など、実践的なアプローチを紹介します。" }, { "title": "GraphQLによるモダンAPIの構築", "content": "GraphQLを使用したAPIの設計と実装について解説します。スキーマ設計、リゾルバの実装、N+1問題の解決、キャッシュ戦略など、実践的な開発手法を紹介します。" }, { "title": "CI/CDパイプラインの自動化戦略", "content": "継続的インテグレーション/デリバリーパイプラインの効率的な構築方法について解説します。テスト自動化、デプロイ戦略、品質管理、モニタリングなど、実践的な自動化手法を紹介します。" }, { "title": "セキュアなWebアプリケーション開発", "content": "Webアプリケーションのセキュリティ対策について包括的に解説します。XSS対策、CSRF対策、認証・認可の実装、セキュアなセッション管理など、重要なセキュリティ考慮事項を説明します。" }, { "title": "効率的なキャッシュ戦略の実装", "content": "Webアプリケーションにおけるキャッシュ戦略の設計と実装について解説します。CDN、ブラウザキャッシュ、アプリケーションキャッシュ、データベースキャッシュなど、多層的なキャッシュ戦略を紹介します。" }, { "title": "大規模データ処理のベストプラクティス", "content": "大規模データ処理システムの設計と実装について解説します。バッチ処理、ストリーム処理、データパイプライン、スケーラビリティ確保など、実践的なアプローチを紹介します。" }, { "title": "ReactとTypeScriptによるフロントエンド開発", "content": "ReactとTypeScriptを組み合わせた最新のフロントエンド開発手法について解説します。型安全な開発、コンポーネント設計、状態管理、パフォーマンス最適化など、実践的な開発テクニックを紹介します。" }, { "title": "AWSでのスケーラブルなインフラ構築", "content": "AWSを使用したスケーラブルなインフラストラクチャの構築方法について解説します。オートスケーリング、負荷分散、障害対策、コスト最適化など、クラウドインフラの設計ポイントを説明します。" }, { "title": "効率的なログ管理とモニタリング", "content": "分散システムにおけるログ管理とモニタリングの実践的アプローチについて解説します。ログ収集、分析、可視化、アラート設定など、効果的な運用監視の方法を紹介します。" }, { "title": "マイクロフロントエンドアーキテクチャの実装", "content": "マイクロフロントエンドアーキテクチャの設計と実装について解説します。モジュール分割、統合戦略、ルーティング、状態管理など、フロントエンド開発の新しいアプローチを紹介します。" }, { "title": "NoSQLデータベースの設計パターン", "content": "NoSQLデータベースを使用する際の効果的な設計パターンについて解説します。データモデリング、クエリ最適化、スケーリング戦略など、実践的な使用方法を紹介します。" }, { "title": "機械学習モデルの本番環境デプロイ", "content": "機械学習モデルを本番環境にデプロイする際の実践的アプローチについて解説します。モデルのバージョン管理、スケーリング、モニタリング、再学習戦略など、運用上の重要ポイントを説明します。" }, { "title": "Terraformによるインフラのコード化", "content": "Terraformを使用したインフラストラクチャのコード化について解説します。リソース管理、モジュール設計、状態管理、チーム開発など、IaCの実践的な適用方法を紹介します。" }, { "title": "効率的なAPIバージョニング戦略", "content": "WebAPIのバージョニング戦略について実践的な方法を解説します。バージョン管理手法、下位互換性の確保、マイグレーション戦略など、長期的な API 運用のポイントを説明します。" }, { "title": "セキュアなマイクロサービス間通信", "content": "マイクロサービス環境におけるセキュアな通信方法について解説します。認証、認可、暗号化、証明書管理など、サービス間通信のセキュリティ確保方法を説明します。" }, { "title": "効率的なデータベースマイグレーション", "content": "大規模データベースのマイグレーション戦略について解説します。ダウンタイム最小化、データ整合性確保、ロールバック計画など、安全なマイグレーションの実施方法を紹介します。" } ] def insert_test_data(): conn = psycopg2.connect( dbname="vectordb", user="postgres", password="postgres", host="postgres", port="5432" ) cur = conn.cursor() embedding = Embedding() for data in test_data: # サンプルとして1536次元のランダムベクトルを生成 emb = embedding.get_embedding([data["title"] + " " + data["content"]])[0] cur.execute( "INSERT INTO documents (title, content, embedding) VALUES (%s, %s, %s)", (data["title"], data["content"], emb) ) conn.commit() cur.close() conn.close() if __name__ == "__main__": insert_test_data() データベースとの接続定義を記述したファイルを作成します。 [connections.postgresql] dialect = "postgresql" host = "postgres" port = 5432 database = "vectordb" username = "postgres" password = "postgres" 依存ライブラリを記述したファイルを作成します。 SQLAlchemy==2.0.35 streamlit==1.32.0 pandas==2.2.0 numpy==1.26.0 psycopg2-binary==2.9.9 torch==2.6.0 transformers==4.48.2 Docker環境のセットアップ まずはpostgresのDockerfileから作成をしていきます。 postgresベースのイメージにpgvectorのインストール処理を追加します。 FROM postgres:16.3 # pgvectorインストール RUN apt-get update && \\ apt-get install -y \\ build-essential \\ git \\ postgresql-server-dev-16 RUN git clone <https://github.com/pgvector/pgvector.git> /tmp/pgvector && \\ cd /tmp/pgvector && \\ make && \\ make install && \\ rm -rf /tmp/pgvector 続けてStreamlitのDockerfileを作成します。 FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt CMD ["streamlit", "run", "./streamlit/app.py", "--server.port=8501"] 最後にこれらのコンテナを束ねて管理するdocker-compose.ymlを作成します。 version: "3.9" services: postgres: build: ./postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: vectordb volumes: - postgres_data:/var/lib/postgresql/data - ./postgres/initdb:/docker-entrypoint-initdb.d ports: - "5432:5432" networks: - app-network streamlit: build: ./streamlit volumes: - .:/app environment: - STREAMLIT_SERVER_PORT=8501 ports: - "8501:8501" depends_on: - postgres networks: - app-network volumes: postgres_data: networks: app-network: driver: bridge 動作確認 起動確認 以下のコマンドでコンテナのビルドを行います。 docker compose build 以下のコマンドでコンテナの起動を行います。 docker compose up -d ブラウザで以下のアドレスにアクセスします。 http://localhost:8501/ 最初はモデルを読み込むためロード中となり、下記のような画面が表示されるかと思いますが その後このような表示になれば、サーバーの起動に成功しています。 初期データの投入 データベースに初期データを投入する為、コンテナ上でコマンドを実行します。 まずはコンテナの状態の確認を行います。 $ docker compose ps NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS pgvector-postgres-1 pgvector-postgres "docker-entrypoint.s…" postgres 2 hours ago Up 2 hours 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp pgvector-streamlit-1 pgvector-streamlit "streamlit run ./str…" streamlit 2 hours ago Up 2 hours 0.0.0.0:8501->8501/tcp, :::8501->8501/tcp 上記で出力されたコンテナの内、streamlitのコンテナ上で以下のようにしてコマンドを実行します。 $ docker exec -it pgvector-streamlit-1 python streamlit/seed.py コマンド実行後に再度ブラウザで以下のアドレスにアクセスします。 http://localhost:8501/ 投入したデータが一覧で表示されるようになりました。 Vector検索の確認 先ほどアクセスした画面の「操作を選択」から「ベクトル検索」を選択します。 上記のような画面が表示されるかと思います。 試しにこちらの検索テキストに「MySQL」と入力して検索してみます。 上記のように結果が表示されました。内容としては以下のようなものですが、もちろん本文に「MySQL」という文言はありません。 内容の指向性や意味などからもっとも類似度の高い内容順に並べることができていることが確認できます。 おわりに 本記事で実践したPostgreSQLベクトル検索システムの構築は、AI時代のデータ活用における重要な第一歩です。 従来のリレーショナルデータベースの枠組みを超え、意味理解を組み込んだ次世代検索技術 を、既存インフラで実現する手法を具体例と共に解説しました。 本格的な導入を検討される方は、まずは pgvector公式ドキュメント と E5モデルに関しての記事 の精読をお勧めします。実際のプロダクション環境では、 インデックス再構築戦略 と メモリ最適化 が成否を分ける鍵となります。 最後に、本記事が皆様のAI/MLプロジェクト推進の一助となれば幸いです。 The post PostgreSQLで実践するベクトル検索入門:AI時代のRDBMS活用術 first appeared on Sqripts .
アバター
こんにちは、QAコンサルタントの ヤマダ です。 私はこのたび、JSTQB® Advanced Level テストマネージャ試験に合格しました。   本記事では、試験合格のために活用した書籍「 科学的根拠に基づく最高の勉強法 」の内容を解説するとともに、JSTQB試験の概要、そして実践した勉強法を共有します。 書籍の紹介:「科学的根拠に基づく最高の勉強法」 この書籍は、医師であり学習法の専門家である著者が、最新の研究論文やデータを基に、科学的に効果が証明された学習法を紹介したものです。特に、次のようなポイントが大きな特徴です。 効果が低い学習法 日常的に行われがちな以下の方法は、実は非効率とされています: 繰り返し読む :一見効果的に思えるが、記憶の定着にはほとんど寄与しない。 ノートに書き写す :時間がかかる割に、記憶や理解が深まらない。 ハイライトや下線を引く :重要箇所をマークする行為そのものに学習効果はない。 効果が高い学習法 1. アクティブリコール(能動的記憶再生) 学習した知識を記憶から引き出すことで、記憶が強化されます。たとえば問題を解く、クイズ形式で学ぶといった方法が該当します。 2. 分散学習 短時間で詰め込むのではなく、間隔を空けて繰り返し復習することで、記憶の定着率が向上します。たとえば、1日おきに復習する、週ごとに学び直すといった方法です。 3. 精緻的質問と自己説明 精緻的質問 :学んだ内容に対して「なぜそうなるのか」と問いかけ、深掘りして理解を深めます。 自己説明 :学習した内容を自分の言葉で説明することで、曖昧な理解を防ぎます。 これらの方法を組み合わせることで、学習効率を大幅に向上させることができます。 JSTQB®の試験とテストマネージャモジュールの紹介 JSTQB®の概要 JSTQB®(Japan Software Testing Qualifications Board)は、ソフトウェアテストの知識と技能を体系的に学び、その理解度を証明する資格試験を提供する団体です。ISTQB®(International Software Testing Qualifications Board)の国際基準に基づいており、ソフトウェアテストの標準資格として広く認知されています。 試験の構成 JSTQB®試験には以下の3つのレベルがあります。 1. Foundation Level 初心者向け。テストの基本概念、設計技法、テスト管理の基礎が試験範囲に含まれます。 2. Advanced Level 経験者向け。3つのモジュールに分かれています。 テストマネージャ :テスト計画やプロジェクト管理に特化。 テストアナリスト :要件分析やテスト設計技法に焦点。   テクニカルテストアナリスト :テストツールや自動化の活用。 3. Expert Level   ソフトウェアテストの最上級資格。リーダーシップやプロセス改善に関する知識を問われます。 Advanced Level テストマネージャの試験内容 テストマネージャは、テストプロジェクトを計画・実行・管理するスキルを証明するためのモジュールです。以下が主な試験範囲です。 テストプロセス :テスト戦略の作成、計画、モニタリング、評価。 リスクベーステスト :リスクを特定し、優先順位を付けてテスト計画を策定。 テストチームの管理 :チームビルディングやステークホルダーとのコミュニケーション。 品質保証 :メトリクス分析やプロセス改善の実施。 ツールと自動化 :適切なツールの選定と導入。 実践した勉強法 以下の3ステップを繰り返しながら学習を進めました。このプロセス全体に書籍で紹介されている学習法を取り入れています。 1. シラバスを読む 方法とポイント 流し読みからスタート :まずはシラバス全体を流し読みし、試験範囲を大まかに把握。 不明点をメモ :分からない箇所や重要そうな部分をメモに記録し、後のプロセスで補強。 関連情報を調査 :シラバスに記載された内容について理解が曖昧な部分は、ChatGPTやWeb検索で調査。 活用した勉強法 分散学習 :シラバスを一度に全部読むのではなく、複数回に分けて学習しました。1日目に全体を流し読み、2日目以降に重点的な箇所を再度読むことで記憶を強化しました。 精緻的質問 :各セクションで「なぜこの方法が重要なのか」「どうしてこれが推奨されるのか」を自分に問いかけながら学習しました。 2. 問題を解く 方法とポイント 問題演習の徹底 :非認定問題集を使いながら繰り返し問題を解き、シラバスの内容を応用する練習を行いました。 間違いの記録 :間違えた問題について、問題番号、対応するシラバスの箇所と間違えた原因をメモ。 ChatGPTを活用 :シラバスと問題集をChatGPTにインプットし、問題集に含まれていない新しい問題を生成してもらうことで、幅広い演習を実施しました。 活用した勉強法 アクティブリコール :問題を解くことで、学習した知識を記憶から引き出し、記憶を強化しました。 自己説明 :解いた問題について「なぜこの答えが正解なのか」「他の選択肢が不正解の理由」を自分に説明しました。これにより、選択肢の背景や理論を深く理解できました。 3. 振り返り 方法とポイント 振り返りは学習の各ステップで必ず行い、学習効率を高めました。振り返りでは、これまでに取った メモ を活用して原因分析を行います。 メモの活用 :シラバスを読んだ際に書き留めた不明点や、問題を解いた際に記録した間違えた箇所やその理由を参照。 原因分析 :「知識不足」「問題文の読み違い」「思い込み」などに分類し、それぞれの対策を実施。 弱点補強 :特に苦手な分野については、再度シラバスを読み直したり、問題を解き直したりして克服を図りました。 進捗の可視化 :日々記録を取っているため、これまで間違えていた問題が出来るようになっていることが分かり、自分の成長を確認しました。 活用した勉強法 分散学習 :振り返りを何度も行い、時間を空けて同じ内容を復習することで、知識の定着を強化しました。新しい知識よりも復習を重視しました。 精緻的質問 :「なぜ間違えたのか」「どのように考えれば正解にたどり着けたのか」を繰り返し問いかけ、理解を深めました。 スキマ時間を活用した学習 スキマ時間を積極的に活用することも、 分散学習 の効果を得るための重要な手段です。以下のように、短時間の学習を複数回に分けて行いました。 通勤時間 :シラバスの読み込みや、理解が曖昧な箇所の復習。 昼休み :問題集を1問でも解く。 夜の15分 :振り返りや弱点補強。 まとめ 「科学的根拠に基づく最高の勉強法」を取り入れることで、学習効率を向上させることができたと思います。この方法は、資格試験だけでなく、日常の学びやスキルアップにも応用可能です。これから受験を目指す方は、科学的なアプローチを試してみてはいかがでしょうか? The post JSTQB Advanced Level テストマネージャ勉強法 -科学的根拠に基づく最高の勉強法を参考にして- first appeared on Sqripts .
アバター
この連載では、ソフトウェア開発のQAエンジニアとして働き始めた皆様に向けて、私の実体験をもとに「こんなことを知っておけばよかった」という、ちょっとした気づきを共有します。 一緒にソフトウェア開発のQAエンジニアとしての充実したエンジニアライフを築くためのヒントを探っていきましょう。 <QAエンジニアのスタートガイド 記事一覧> ※クリックで開きます 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- 【第4回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -後編- 第3話ではソフトウェアテストにおける「テスト実行」について、テスト活動における重要さと、充実させるポイントをお話ししました。「テスト実行」を実際に体験し、そこから学ぶことは大変重要なことだと思っています。 一方で、テスト実行を支えるその他の活動を理解することも大切です。そして、QAエンジニアとして大切なことは、これらの活動についてきちんと理解したうえで、「テストをマネジメントする」という考え方をすることです。 今回の記事ではテスト実行以外の活動について解説します。そして、それらの活動を踏まえた上で、さらにステップアップを目指す内容についてご紹介します。 テスト実行を支えるその他の活動 テスト計画・テスト設計といったその他のテスト活動は、テスト実行を支える活動と言ってもいいと思います。この記事では、テスト実行をベースにその他の活動を捉えることで、よりテスト全体への理解を深めることを目的としています。 この記事が、テスト実行以外の活動を実施する際の一助となれば幸いです。 テスト設計 本記事では、JSTQBにおける「テスト分析」「テスト設計」「テスト実装」を総称して「テスト設計」と呼びます。「テスト設計」という名前のプロセスや成果物は、実はチームや組織、文献によっても異なるからです。 そういった背景がありつつも、「テスト設計という活動によってテストケースを作成する」というところは共通理解として成り立つのではないでしょうか。 テスト実行中にテスト設計について気にするポイントとしては、「なぜこのテストケースを作成したのか」を考えることです。 もしかしたらテストケースの中には「テスト条件」「テスト観点」「テスト項目」といった項目があるかもしれません。それらの内容から、「テストを実行する理由」を探してほしいと思います。これらを念頭に置いた上で、「実際にどのようなテストケースでカバーしているか」「どのような思考でテストケースを作っているか」を考えることはQAエンジニアとして重要な学びに繋がると考えます。 テストのモニタリングとコントロール テストのモニタリングとコントロールという活動は、スケジュールや人のアサインの調整だと思われている方がいます。それらは重要な管理対象であることに間違いありませんが、それだけではありません。 たとえば、テスト実行で得られた情報を元に、テスト実行の順番を調整したり、テストの追加・削除を検討することもあります。他にもテストの開始基準や完了基準を再検討して、テスト計画をアップデートすることも含まれます。 テスト実行をしていて気にするべきポイントは、「テストのモニタリングとコントロールのためにどのような情報を収集しているだろうか」「それらによってどのような意思決定がされただろうか」だと考えます。 テストをただ消化するだけでなく、消化したテストによってどのような判断がされたかを理解することは、ご自身がテストをマネジメントする立場になったときに活きてくるでしょう。 テスト完了 「テスト完了」はテスト活動の集大成という側面や、次のテストのプロジェクトのために学びを活かすなどの側面があります。 所属する組織で「テスト完了レポート」を作成している場合、ぜひ一読されることをおすすめします。 我々のテスト活動が、ステークホルダーへどのように報告されるかを知ることができるからです。それによって、「我々のテストで重要なのはどの部分だったのか?」「我々のテスト活動を待っている人々は何が知りたかったのか?」を理解することができます。 また、完了報告のミーティングに参加することも学びに繋がります。これは、テスト活動において、どのようなニーズがあったのかを知り、ステークホルダーの反応を知るよい機会になります。 テスト計画 テスト計画の成果物であるテスト計画書は、その現場のテストを理解するにあたって、最も重要なドキュメントのひとつです。テスト計画書には、通常、「テストの目的」「テストにおける制約」「最適なアプローチ」「完了のための手段」などが記載されています。 ひいてはテスト実行の活動がどのような意味を持ち、どのような文脈の中で、どんな実行計画を立てたのか、その中で自分はどのような位置にいるのかを知ることは普段の仕事の目的意識を持つためにも重要です。 アジャイル開発などのプロジェクトでは、テスト計画という活動やテスト計画書といった成果物がない場合もあります。その場合でも上記のような観点で「どのようにテストを計画しているのだろうか」を考えることは学びに繋がります。 QAとして「テストをマネジメントするという」考え方を持とう ソフトウェアテストには「テストマネージャー」というロールがあります。彼らは「テストマネジメントをする」という役割を持っています。そのような役割を持った人がいるために、「テストマネージャーになるまでテストマネジメントはしなくていい」と考える人もいます。 この考えはQAエンジニアのキャリアや働き方にとって、ポジティブな意味を持たないと私は考えています。 自分のチームがテストを通して「どのような情報を取得したか」「どのような意思決定をしたか」についてきちんと把握することで、QAとして重要な「目的意識」を養うことができます。 読者の方の中には、自分一人で意思決定をすることはない人もいるかもしれません。 しかしながらそのための情報提供や、自分の専門性を元にチームへ示唆を与えることは必要だと考えています。 特に、「QAエンジニア」というロールの場合は、テストマネージャーではなくても「テストをマネジメントする」という考えを持つ必要があると考えます。 QAの責務を「テストの仕事を収める」ではなく、「品質を保証すること」であると考えるのはいかがでしょうか。 テストという分野においては、単にテストを消化するだけでなく、効果的にテストを行なう必要があります。そのために常に「テストマネジメント」の意識を持っておくことが重要になるのです。 QAエンジニアに求められるテストの周辺知識 テストエンジニアではなく、あえて「QAエンジニア」と名乗るからには、テストだけでなくもう少し広い知識をつけることも大切だと考えます。 ここからは、さらに飛躍するための知識について紹介します。 自動テスト 自動テストの知識は、QAエンジニアにとって必須になりつつあります。手動でテストの活動をするだけでなく、自動テストについてきちんと理解して・作り上げる知識を持つことが大切です。 自動テストを考える過程でテスト全体に向き合うこととなりますので、テストレベルやテストマネジメントへの理解が深まるという効果もあります。 品質管理 品質管理は、ソフトウェア開発よりも長い歴史を持つ分野であり、関連書籍も多数出版されています。これらについて深く理解することは、QAとしての考えの軸を定めるのに効果的です。 ひとつ補足をすると、ソフトウェア開発と、量産工程がある製品の開発は、品質管理のプロセスが異なります。そのため、単純にすべてのプラクティスを使うことには注意をした方がいいでしょう。 ソフトウェアエンジニアリング 私は「ソフトウェアエンジニアリング」を学ぶことが最も大切だと考えます。ここでいう「ソフトウェアエンジニアリング」とは、モデリングやプログラミングなど、ソフトウェア開発におけるさまざまなプラクティスを指します。 特にプログラミングについては、エンジニアでなくでもPCを使う全ての職種で必要になる技術だと考えます。 QAのハードスキルを手に入れるための参考文献 ソフトウェアテストについて知りたい場合、最も手軽なのは「JSTQBシラバス」です。専門用語が多く、最初はとっつきにくいですが、一読することをおすすめします。 ソフトウェアテストについての書籍を紹介しておきたいところですが、「この本さえ読んでおけば大丈夫」という本は私が読んだ中では存在しません。それぞれの書籍によって見解や専門分野が異なるためです。 そのため、さまざまな文献を多読して、自分なりのテスト観を育てることが大切です。 ソフトウェアテストの学習と参考になるのが、以下の「ソフトウェアテストの読書マップ」です。 ソフトウェアテスト読書マップ QAとしては SQuBOK(ソフトウェア品質保証知識体系) を一度読んでみることをおすすめします。 SQuBOKでは、ソフトウェアQAに必要な知識が網羅的に解説されています。 「この状況ではどんな方法があるんだっけ」というインデックスを早期に作っておくことは、QAエンジニアの経験を豊かにする良い方法だと考えます。 ソフトウェアエンジニアリングの本もおすすめです。特にQAに関係する方が翻訳している「 実践ソフトウェアエンジニアリング 」という本は、全体像を把握できるので、ぜひ手にとってみてください。 おわりに 第3話、第4話と続いた「ハードスキル」の紹介ですが、ITエンジニアにとってハードスキルの学習に終わりはありません。 この記事の内容に満足するのではなく、さまざまな分野に興味を持って、主体的に学習することをおすすめします。 【連載】QAエンジニアのスタートガイド 記事一覧 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- 【第4回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -後編- The post 【第4回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -後編-|QAエンジニアのスタートガイド first appeared on Sqripts .
アバター
この連載では、1人目QAとしてのチームの立ち上げや組織づくりに関して、私が実践したことや試行錯誤中のことも含めてお伝えします。 前回の記事 では、開発者とQAとのコミュニケーションに関する問題やその対応について解説しました。 【第4回】QAと開発者とのコミュニケーション|QA組織の立ち上げ方 この連載では、1人目QAとしてのチームの立ち上げや組織づくりに関して、私が実践したことや試行錯誤中のことも含めてお伝えします。前回の記事では、チームビルディングの概念や考え方の説明と、QAチームにおけるチームビルディングについてタックマンモデルの各段階...  続きを読む  Sqripts 関連記事|Sqripts 今回は、QAチームを立ち上げていく過程でメンバーのキャリアをどう作っていくかを考えます。 チーム立ち上げにおけるメンバーのキャリアパス QAチームを立ち上げ成長させていく上で、メンバーのキャリアパスは重要なテーマです。とくに、立ち上げ初期のメンバーや若手エンジニアにとっては、チームでの活動を通じて将来どのようなキャリアを描けるのかが重要です。明るい未来が見通せるかどうかは、日々のモチベーションや成長に大きく影響します。 そこで、今回はQAチームにおけるキャリアパスを 社内でのキャリア 社外でのキャリア という2つの側面から掘り下げてみたいと思います。 社内でのキャリアパス QAエンジニアとして自社で働く過程で、どのような経験を積みどのような道に進めるのか、具体的なキャリアビジョンを示すことが不可欠です。 ビジョンを示すことの重要性 中堅・ベテランにもなれば「キャリアは自分で考えて築くもので、会社がすべて考えるわけではない」と言えるのですが、キャリア形成の初期段階にある若手エンジニアに対してはそうはいきません。QAチームを組成して数年が経ち、社内での役割・位置づけ・評価の仕方などが固まっている場合は、キャリアの見通しがつきやすいでしょう。しかし、本記事が対象としている「QAチームの立ち上げ」の段階においては、QAエンジニアとして働いた先のイメージが持ちづらくなります。 もちろん暫定ではあると思いますが、QA組織を将来どうしたいかのビジョンとともに ジュニアなQAエンジニアも含めて、QAチームのマネジメントを担えるようになる SETとしてテスト自動化等に強みを発揮する など複数の選択肢を提示できると良いでしょう。 このとき、 第1回 でも触れたQMファンネルを参考に、テストエンジニア・パイプラインエンジニア(SET)・QAエンジニアといった軸で検討をするとわかりやすいです。さらに、各ロールにおけるスプリット・インプロセス・コーチ・コンサルタント・プロモーターといった役割を組み合わせることで、より多様なキャリアパスを描くことができます。 【第1回】QA組織立ち上げの流れと組織の形 以前の連載である1人目QAとしての立ち回りでは、会社や開発組織の1人目QAになった人がどのような活動をするのかや、品質保証を浸透させる際のアプローチなどについて触れました。今回の連載では1人目QAとしてチームを立ち上げていく部分、組織づくりに関して、私が実...  続きを読む  Sqripts 関連記事|Sqripts 社外でのキャリアパス QAチームを立ち上げる際、社外でのキャリアパスを考慮することは、一見するとチームの安定を損なうように思えるかもしれません。「せっかく育てたのに、転職してしまうのではないか?」という懸念を抱く方もいるでしょう。しかし、個人的にはむしろ積極的に社外キャリアを一緒に考える方が、長期的に良い関係を築けると信じています。 QAエンジニアが抱える不安 私は他社でQAエンジニアをされている方から相談をいただく機会があるのですが、その中で「今の自分の仕事は、本当にQAとして正しいのか?」「他の会社ではどうしているのか?」といった不安を感じている方が少なからずいらっしゃいます。自社だけでQAエンジニアの基準や業務を考えると、どうしても視野が狭くなりがちです。このときにやるべきことは、 世の中全体のQAの動向を把握し、その中で自分たちがどのような立ち位置にあるのかを理解すること だと考えます。 他社では開発チームとQAチームが完全に分かれているところもあるらしい ウチでは開発者がE2Eテストを書いているけれど、QAエンジニアが書いているところもあるらしい など、いろいろなパターンのQA組織・QAエンジニアの業務スコープがあると知ることも、とくにジュニアなメンバーにとっての安心感につながります。世の中のQAのトレンドや、最先端の技術、他の企業での取り組みを知ることで、自社の活動を相対的に把握できます。これは優劣をつけるのではなく、あくまでも「状況に応じて正解がいろいろある」と知ることが大事、という意味です。 その結果「自社ではスコープ外になっているけれど、どうしても挑戦したい領域がある」というメンバーがいて、残念ながらチームや会社を離れてしまうこともあるかもしれません。チームを立ち上げている身としてはつらいところですが、これは受け入れるしかありません。自社のQAエンジニアとしての未来に不安を抱えたまま退職をされるよりは、前向きなチャレンジのためにと巣立ってもらうほうがよい、と捉えましょう。 チームを立ち上げる側の役割 世の中のQA組織の形やQAエンジニアの仕事の動向≒「全体感」をメンバーに持ってもらうためには、チームを立ち上げる側の努力が必要です。 組織を立ち上げるQAエンジニア本人が世の中の動向を把握し、最新の知識をアップデートしておく必要があります。ただし、すべてを把握した上でメンバーに教えようと考えると大変です。QAチームを立ち上げる側がざっくりと掴んだ情報を伝えつつ、一緒に解像度を高めていくというイメージで、メンバーのキャリアを支援することが望ましいでしょう。JaSSTなどのイベントに一緒に参加して他社と情報交換しつつ全体感を捉えるのもよいですね。 社内・社外両面でキャリアパスをフォローする QAチームを立ち上げる際には、メンバーの社内外でのキャリアパスをともに考え、長期的な成長を支援することが重要です。 社内のキャリア:チームのビジョンを定め、進むべき方向の選択肢を提示する 社外のキャリア:業界全体の動向を共有し、自分たちの位置づけを把握してもらう という両面でフォローすることで、メンバーの成長にも繋がり、結果としてQAチームが強化されるでしょう。 【連載】QA組織の立ち上げ方-1人目QAが語る実践と工夫- 記事一覧 【第1回】QA組織立ち上げの流れと組織の形 【連載初回、全文公開中】 【第2回】2人目以降のQAエンジニアの採用 【第3回】QAチームビルディング 【第4回】QAと開発者とのコミュニケーション 【第5回】QAチームにおけるキャリアの作り方 The post 【第5回】QAチームにおけるキャリアの作り方|QA組織の立ち上げ方 first appeared on Sqripts .
アバター
こんにちは、AGESTでエンジニアをしているタカです。 今回は、最近話題のAI活用型コードエディタ「Cursor」のComposer機能を使って、簡単なNext.js製Webアプリケーションを開発し、CI/CDパイプラインを構築してGoogle Cloudの環境にデプロイする、という一連の流れに挑戦します。 目的は、個人的にCursorの操作に慣れることと、直近で触れていなかったGoogle Cloudの設定やCI/CD周りの知識を思い出すことです。実践を通して、これらのスキルをブラッシュアップできればと思っています。 ちなみに、CursorエディタやComposer機能の基本的な使い方については、2024年10月に公開されたこちらの記事で詳しく解説していますので、併せてご覧ください。 CursorのComposer機能でAIに0からテストコードを作成してもらう こんにちは、AGESTのバックエンドエンジニアのまさです。今回は、CursorエディタのComposer機能を用いて、AIにテストコードを記述してもらう方法をご紹介します。テストコードはソフトウェアの品質を高めるために重要ですが、手作業で書くのは時間がかかるものです。...  続きを読む  Sqripts 関連記事|Sqripts Webアプリケーションのシステム構成について 今回は、あくまでCursorを使った開発に焦点を当てたいので、Google Cloud上のインフラ構成は、できる限りシンプルにすることを意識しました。具体的には、以下のような構成で進めます。 CI/CDパイプラインはGitHub Actionsで構築:  アプリケーションのビルド、テスト、デプロイはGitHub Actionsを使って自動化します。 アプリケーションはCloud Runに直接デプロイ:  Container Registryを経由せず、Cloud Runに直接デプロイします。これにより、手順を簡略化します。 Load BalancerやCloud Armorは使用しない:  これらの機能も便利ですが、今回は扱う範囲が広くなりすぎてしまうため、見送ります。必要に応じて、今後の記事で取り上げたいと考えています。 IaC (Infrastructure as Code)は使用しない:  今回はTerraformなどのIaCツールは使用せず、手動で設定を行います。 開発環境については GitHub Codespaces 上に構築: ローカル環境を汚さず、かつ、どこからでも同じ環境で開発できるようにする プロンプト1(Webアプリケーション) さて、ここからは実際にCursorにコード生成を依頼してみます。まずは、どのようなプロンプトでコード生成を依頼したのか、その内容と結果について掲載します。 初回は、以下のようなプロンプトで、Cursorの生成AIモデルとしてgpt-4oを指定して依頼してみました。 Webアプリケーションを構築したいです。 以下の条件でファイルの生成や手順を提示してください ----------------------------------- # リポジトリ * GitHubで作成したリポジトリをcloneしてcursorで現在開いています。ファイルを作成してください。 * gitの操作は把握済みなので、commit、pushなどは自分で行います。手順から省いてください。 # 開発環境 * GitHub CodeSpacesを使用します。 * ローカルのIDEはCursorを使います。CursorからGitHub CodeSpacesの接続手順を提供してください。 # アプリケーション * Next.jsで構築してください。まずはデフォルトで良いので、コマンドでの構築手順を提供してください * 今後、データベースやAPIのサーバーを立てる可能性がありますが、今回は不要です。 # インフラ * DockerコンテナにてWebアプリケーションを立ち上げてください * いずれTerraformでインフラ管理を行いますが、今回は不要です。 # 本番環境 * Google Cloud の Cloud Runにデプロイを行います。東京リージョンを使用してください。 * GitHub Actionsのワークフローを作り、CI/CDを行ってください。 * デプロイのために必要なシークレットの情報を提供してください。権限情報が必要だと思います。 ----------------------------------- プロンプト1の出力結果 生成された出力結果を全て貼り付けると長いため、ここでは概要のみ掲載します。以降の記事で必要に応じてキャプチャを掲載します。 1. Next.jsアプリケーションのセットアップ npx create-next-app@latest 2. GitHub CodeSpacesのセットアップ GitHubリポジトリで「Code」ボタンをクリックし、「Open with Codespaces」を選択します。 新しいCodespacesを作成するか、既存のものを選択します。 3. Dockerコンテナの設定 4. GitHub ActionsによるCI/CDの設定 5. 必要なシークレット情報 GCP_SA_KEY: Google Cloudのサービスアカウントキー(JSON形式) GCP_PROJECT_ID: Google CloudのプロジェクトID** この出力結果を見ると、少し順番を前後させた方が良い箇所もありますが、概ねやりたいことは実現できそうです。 プロンプト1で自動生成されたファイル 3、4の手順では、Cursorにより、 ファイルが自動生成 されました。以下に内容を記載します。 # ベースイメージ FROM node:16 # 作業ディレクトリの設定 WORKDIR /app # package.jsonとpackage-lock.jsonをコピー COPY package*.json ./ # 依存関係のインストール RUN npm install # アプリケーションのソースをコピー COPY . . # ビルド RUN npm run build # ポートの設定 EXPOSE 3000 # アプリケーションの起動 CMD ["npm", "start"] Dockerfile name: Deploy to Cloud Run on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up Cloud SDK uses: google-github-actions/setup-gcloud@v0 with: project_id: ${{ secrets.GOOGLE_CLOUD_PROJECT_ID }} service_account_key: ${{ secrets.GOOGLE_CLOUD_SERVICE_ACCOUNT_KEY }} - name: Deploy to Cloud Run run: | gcloud run deploy my-nextjs-app --source . --region asia-northeast1 プロンプト2(動作確認手順) プロンプト1では、アプリケーションに必要なファイルの生成に成功しましたが、動作確認の手順については言及されていませんでした。そこで、今回は動作確認に焦点を当てたプロンプトを作成し、Cursorに追加で指示を出します。 以下に、今回使用したプロンプトの全文を記載します。 開発の方法として段階を踏んで動作確認を行いたいと思います。 * まずは、CodeSpaces上でアプリケーションの構築を行ったうえで、 Dockerコンテナを起動し、ブラウザでエンドポイントにアクセスして表示が問題ないことを確認します。 * 次にワークフローを構築しますが、動作確認をCodeSpaces上でactというツールで行いたいです。 * 動作確認が問題なければ、mainブランチにマージしてワークフローを動かして Google Cloudにデプロイします。 これらのコマンドなどを示してください プロンプト2の出力結果 生成された手順は少し長いため、ここでは概要のみを掲載します。 1. CodeSpaces上でのアプリケーション構築と確認 2. Google Cloud Runへの手動デプロイ 3. GitHub Actionsワークフローの設定とローカルテスト 4. Google Cloudへのデプロイ この動作確認手順に従って、以降の記事を進めていきます。 1. CodeSpaces上でのアプリケーション構築と確認 CodeSpacesへのアクセス まずは、GitHub Codespaces上に開発環境を構築し、そこでNext.jsアプリケーションのセットアップと動作確認を行います。 GitHub Codespacesの起動は、本来であれば、Cursorのリモートエクスプローラーから行えるはずでした。 しかし、残念ながらこの記事の執筆時点では、CursorからGitHub Codespacesへの接続がタイムアウトしてしまい、正常に動作しませんでした。 そのため、今回は代替策として、ブラウザでGitHub上から直接Codespacesを作成してログインすることにしました。コードに関してはCursor上でpushし、ブラウザのCodespacesでpullするという流れになります。 Next.jsアプリケーションの起動と Dockerビルドエラーへの対処 続いて、Next.jsアプリケーションのセットアップを行い、Dockerコンテナを起動してみます。今回は、Next.jsのデフォルトアプリケーションをそのまま利用したため、セットアップ自体は非常に簡単でした。 ただし、Dockerコンテナの起動ではビルドエラーがいくつか発生したため、エラーメッセージをCursorに貼り付け、解析と自動修正を行いました。 なお、本来Cursorでは、キャプチャ画像に表示されている「 Run」アイコンをクリックすることで、自動的にコマンドを実行しますが、今回はブラウザのCodeSpacesが開発環境のため npx や docker コマンドをコピー&ペーストして実行しています。 結果として、初期生成のDockerfileから自動修正した差分は以下の通りとなりました。 # ベースイメージ - FROM node:16 + FROM node:20 # package.jsonとpackage-lock.jsonをコピー - COPY package*.json ./ + COPY my-app/package*.json ./ # アプリケーションのソースをコピー - COPY . . + COPY my-app/. . また、参考までに、ディレクトリ構成は以下のようになりました。 赤字がCursorでの自動生成ファイル、青字がnpxコマンドで生成されたNext.jsのアプリケーションファイルです。 . ├── .github │ └── workflows │ └── deploy.yml ├── Dockerfile ├── README.md └── my-app ├── README.md ├── eslint.config.mjs ├── next.config.ts ├── package-lock.json ├── package.json ├── public │ ├── file.svg │ ├── globe.svg │ ├── next.svg │ ├── vercel.svg │ └── window.svg ├── src │ └── app │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ ├── page.module.css │ └── page.tsx └── tsconfig.json 今回はシンプルな構成のため、Cursorで生成されるファイル数は少ないですが、仮にTerraformでインフラの管理を行う場合などは、生成するファイルが増え、Cursorの力が発揮される場面が増える見込みです。 2. Google Cloudへの手動デプロイ アプリケーション起動が確認できたので、次はCodeSpaces上からGoogle Cloudへ手動デプロイします。手動デプロイの手順についてCursorに出力を指示したところ、以下のような手順が提示されました。 1. Google Cloud SDKのインストール 2. Google Cloudにログイン: gcloud auth login 3.プロジェクトの設定 gcloud config set project YOUR_PROJECT_ID 4. Cloud Runへのデプロイ gcloud run deploy my-nextjs-app --source . --region asia-northeast1 Google Cloud SDKのインストール gcloudコマンドを利用するため、まずはGoogle Cloud SDKをインストールする必要があります。インストール手順については、 Google Cloud公式サイト を参照し、apt-getやcurlなどのコマンドを利用して、CodeSpacesにインストールを行います。 CodeSpaces上での実行のため、手順1.と同様に、Google Cloudへのログイン、プロジェクトの設定、Cloud Runへのデプロイコマンドを、コピー&ペーストで実行しました。 デプロイ完了後に、表示されたURLにブラウザでアクセスしたところ、無事にアプリケーション画面が表示されることを確認できました。 3. GitHub Actionsワークフローの設定とローカルテスト 次はいよいよGitHub Actionsを使ったCI/CDパイプラインの構築に取り掛かります。 シークレットの設定 まずは、GitHub ActionsでGoogle Cloudにアクセスするために必要なシークレットを手動で設定します。具体的には、以下の2つをGitHubリポジトリのSecretsに登録します。 Google CloudプロジェクトID Google Cloudサービスアカウントの秘密鍵 なお、サービスアカウントの作成と秘密鍵の取得は、Google CloudのIAM(Identity and Access Management)の画面から行います。 サービスアカウントのロールは、Cloud Run関係で充分かと考え、まずは下記を割り当てました。 この時点でサービスアカウントに割り当てたロール actでのワークフロー動作確認 GitHub Actionsのワークフローは、設定ミスがあると何度もトライ&エラーが必要になることが多いです。そこで今回は、CodeSpaces上でactというツールを使って、ワークフローのローカルテストを行うことにしました。 actを使うことで、GitHub Actionsのワークフローをローカル環境で実行でき、本番環境への影響を最小限に抑えて動作確認を進めることができます。 https://github.com/nektos/act インストールと設定は以下のコマンドを実行しました。 $ curl -s <https://raw.githubusercontent.com/nektos/act/master/install.sh> | sudo bash $ ./bin/act --secret-file .secrets ※実行して表示される選択肢は Medium を選択。 実行コマンドのオプションですが、actでシークレットを使うためには、 .secrets というファイルを作成し、そこにシークレットを記述した上で、–secret-fileオプションで読み込ませる必要があります。 actの動作確認と修正 動作確認で判明しましたが、最初に設定したサービスアカウントはロールが不足しており、エラーが発生したため、このエラーログをCursorに貼り付け、解決を試みました。 Cursorは、具体的なロール名を直接教えてくれるわけではありませんでしたが、関連する情報を提供してくれたため、Google Cloudのコンソール画面でのロール検索や公式ドキュメントを参照して、以下の画像のロールをサービスアカウントに割り当てることで解決しました。 最終的に、actでワークフローを実行した際のデプロイログは以下の通りです。 [Deploy to Cloud Run/build] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/2] user= workdir= | Building using Dockerfile and deploying container to Cloud Run service [my-nextjs-app] in project [***] region [asia-northeast1] | Service [my-nextjs-app] revision [my-nextjs-app-00002-zs9] has been deployed and is serving 100 percent of traffic. | Service URL: <https://my-nextjs-app-346239942346.asia-northeast1.run.app> [Deploy to Cloud Run/build] ✅ Success - Main Deploy to Cloud Run [Deploy to Cloud Run/build] ⭐ Run Post Set up Cloud SDK [Deploy to Cloud Run/build] 🐳 docker exec cmd=[/opt/acttoolcache/node/18.20.5/x64/bin/node /var/run/act/actions/google-github-actions-setup-gcloud@v0/dist/post/index.js] user= workdir= | Skipping credential cleanup - "export_default_credentials" is false. [Deploy to Cloud Run/build] ✅ Success - Post Set up Cloud SDK [Deploy to Cloud Run/build] Cleaning up container 注意点:  actでワークフローを実行すると、実際にGoogle Cloudへのデプロイまでが行われます 4. GitHub Actionsによる自動デプロイ actを使ったローカルテストでワークフローの動作確認が完了したので、最後にGitHub Actionsによる自動デプロイを実行します。 mainブランチへのpushをトリガーとしてCI/CDパイプラインが動き、アプリケーションがGoogle Cloudに自動でデプロイされることを確認しました。 おわりに:AIを活用した開発を振り返って 開発スピードと効率の大幅な向上 今回の開発を通じて、AIを活用することで、トライ&エラーのサイクルを高速に回せるようになったことを実感しました。 特に、コード生成やエラー解決において、Cursorが強力なサポートツールとして機能したことで、開発スピードが向上し、効率的な開発が可能になったと感じています。 AIの活用には基礎知識が不可欠 一方で、AIを効果的に活用するためには、開発者自身にも一定レベルの基礎知識が必要であることを改めて認識しました。 例えば、GitHubへのコードpushや手順3のGoogle Cloudでのユーザープロファイル生成など、セキュリティ上の理由から、人間が介在する必要がある操作は依然として存在します。 また、AIが生成したコードをそのまま使用するのではなく、内容を理解し、必要に応じて修正する能力も必要になります。 AIは開発の強力な「補助輪」 今回の経験から、AIは開発の「丸投げ」ではなく、あくまで「補助輪」であるという認識を強くしました。 AIは、開発者の作業を大幅に効率化してくれる一方で、 最終的な判断 や 責任 は依然として開発者が担う必要があります。このため、AIの得意なことと苦手なことを理解し、適切な役割分担を行うことが重要となります。 最後に 今回の記事では、特にソースコードの生成や、エラーの解決をCursorによって効率的に行うことができました。CodeSpaces上での実行のため、ソースコードはpushとpull、コマンドはコピー&ペーストという手間を挟みましたが、本来は生成されたコマンドを直接実行することが可能です。 Cursorを活用する中で、当初の目的だった直近で触れてこなかった技術領域の知識を思い出し、また、更に知識を深めることができたと実感しています。 今後、AIにどこまでを任せ、どこからを人間が担当するのか、その境界線は変化していくとは思います。しかし、AIによって開発の学習コストが大幅に下がったことは間違いないので、今後もAIを賢く活用し、より効率的で創造的な開発を目指していきたいと思います。 The post Cursorで手軽にWebアプリ開発!AIアシストで自動デプロイを実装 first appeared on Sqripts .
アバター
みなさんこんにちは。 「ソフトウェアレビューをエンジニアリングっぽく捉える会」 の”きたのしろくま”です。 これから6回に渡って「ソフトウェアレビュー」についてのリレー投稿を開始します。 私たちは何者か? 私たち「ソフトウェアレビューをエンジニアリングっぽく捉える会:Software Review Engineering Explorers/SReEE(スリー)(以降、SReEE、とします)」は、2017年頃から月一度のペースで「ソフトウェアレビューをエンジニアリングっぽく捉える」ことを目指してあれこれ議論をしています。 実務におけるレビュー実践事例やカンファレンスでのレビュー関連の発表内容~メンバーがとある出来事で感じたことなど議論する題材はいろいろです。 私たちの関心事に対する議論がある程度まとまって話ができる状態になったり、発信したいメッセージが明確になった時点でソフトウェアレビューシンポジウム(JaSST Review)に組み込むなどして情報を発信してきました。 【参考:最近のソフトウェアレビューシンポジウム(開催レポート)】 JaSSTソフトウェアテストシンポジウム-JaSST Review'23-レポート  詳細はこちら  www.jasst.jp 関連情報 JaSSTソフトウェアテストシンポジウム-JaSST Review'22-レポート  詳細はこちら  www.jasst.jp 関連情報 JaSSTソフトウェアテストシンポジウム-JaSST Review'21-レポート  詳細はこちら  www.jasst.jp 関連情報 そう、私たちはJaSST Review実行委員会のコアメンバーでもあるのです。 どのような内容なのか? このリレー投稿では、研究会で議論した結果を、、、いや、議論中(過程)の内容を発信します。 まだ検討過程なので、研究会としての統一見解や確定した内容を発信するものでもありません。 レビューは自由度が高く、対象範囲も広いため、おぼろげながら全体像が見えてきた(と思っているだけかもしれない(汗))、、、という状態。 このままではいつまで経っても世に情報が発信できない。ということで今回は、投稿を担当するメンバーが、それぞれの担当テーマに対する自らの認識や想い、自分なりの整理を記述することにしました。 そのため、投稿した記事間の整合が取れない部分が発生する可能性があることにご留意ください。 実験的にわれわれの考えを世に送り出してみなさんからの(そして、投稿後に自ら気づくw)フィードバックがあれば必要に応じて見直す。これを繰り返して内容の精度を上げていく「公開レビュー&手直し方式」を採用した投稿となっています。 よって、一度公開した記事も適宜見直していく可能性があります。 この投稿を通じてみなさんと対話でき、私たちが気づかなかったことを認識できることも楽しみにしています。 投稿予定コンテンツ 現時点で投稿を予定しているコンテンツと担当者を以下に示します。 記載順に投稿していくのではなく 、それぞれの担当者の準備ができ次第投稿することになります。 毎回次に何が出るかはお楽しみにしてください。 ※()内はXアカウント名です。 #0 イントロダクション (←いまココ):きたのしろくま( @kitanosirokuma ) #1 レビューとは? :うれっしー( @ureshino66 ) #2 何のためにやるの? :弦音( @tulune ) #3 レビューの観点 :ブロッコリー( @nihonbuson ) #4 レビューファシリテーション :ぱいん( @pineapplecandy ) #5 レビュー評価・ふりかえり :きたのしろくま( @kitanosirokuma ) #6 まとめ :ブロッコリー( @nihonbuson ) 当投稿におけるレビューの全体像と用語定義 現時点で私たちがレビューをどのように見ているかを示します。 図1:当連載におけるレビューの全体像 今回はこの図をベースにリレー投稿を行います。 図1に示した要素を簡単に説明しておきます。 レビュープロセス : 「ISTQBテスト技術者資格制度Foundation Levelシラバス」で示されている作業成果物のレビュープロセス レビュー思考プロセス : レビュープロセスのうち、レビュー対象をどのように確認して結果を出力するのか?を実践する部分を切り出したもの(レビューをエンジニアリングっぽく捉えるメイン対象がこちらです)。 レビューマネジメントプロセス : レビュープロセスのうち、レビューを計画し、実施状況を把握し、実施結果を判定する部分を切り出したもの。 レビューに関わる関係者 : レビュープロセス群に関わる関係者のうち、今回の投稿で取り扱う方たち。 レビューア : レビュー対象を確認して結果を示す人。主にプロジェクトに携わっている人、特定分野の専門家、その他のステークホルダー等であることが多い。 作成者 : レビュー対象の作業成果物を作成し、修正する人。 ファシリテーター : 調整、時間のマネジメント、誰もが自由に発言できる安全なレビュー環境など、レビューミーティングを効果的に運営する人。 おわりに 当初から一緒にソフトウェアレビューについて議論してきた電気通信大学の西康晴さん(以降、にしさん、とします)が2023年に急逝されました。しばらくはその事実を受け入れられず途方に暮れていましたが、にしさんの意思を引き継いで議論を再開・継続しています。 もともとはにしさんの呼びかけで始まった会ですので、今回の投稿はにしさんなくしては語れない内容であることをお伝えしておきます。 では、このあと投稿を開始しますのでよろしくお願いします。 参考情報  ISTQBテスト技術者資格制度 Foundation Level シラバス 日本語版 Version 2023V4.0.J02 この記事を担当したメンバー きたのしろくま(安達 賢二) 自律・自己組織化を促進する価値共創プログラムSaPIDをベースに三方よしとなる新しい価値を一緒に考えて創る「共創ファシリテーター」として活動中。 https://www.softwarequasol.com/ The post [#0]イントロダクション|ソフトウェアレビューをエンジニアリングっぽく語ってみる first appeared on Sqripts .
アバター
はじめまして、クオリティマネージャーのヒロたです。シフトレフトの有効性は皆さんもご存じのことと思いますが、本日は単体テストについて考慮する点と良い単体テストについてご紹介します。 単体テストとは 単体テストはシステム開発におけるテスト工程の一つで、結合テストや総合テスト(システムテスト)、運用テストの前に行われるものです。つまり、テスト工程で最初に実施するテストということになります。主に開発者が行い、各関数やメソッドの動作を確認するために使用されます。一般的には、少ないコードでテストすることから不具合の原因を特定しやすく修正も容易になります。プログラミングを担当した開発者がプログラムを組んだ直後に実施できることから、その機能がどのような動作をするべきかというイメージが鮮明な状態でテストが行えるため、精度の高い検証効果が期待できます。 単体テストのメリット 単体テストの結果、意図した動作をしないことがわかった場合に単体テストが最小単位で行われることから、問題の個所の特定や修正がしやすい。 開発全体のバグ修正コストを下げる効果が高い。 低コストで短時間で結果が得られる。 テストフレームワーク ※1 を使ってテストの自動化が可能。 ※1  Java アプリケーションのJUnit、.NETアプリケーションのNUnitなど自動実行がサポートされています。 単体テストのデメリット テストコードを作成するのに工数がかかる テストコード自体は、自動化できないのでコーディング担当者が、一つひとつ作成しなくてはならない。 テストの精度が実施者のスキルに依存する テスト項目の策定にはスキルが必要となる。制御フローテストでは多くのテストパターンを試す必要があるが、時間は限られているためいかに最適なパターンを作成し、組み合わせるかが重要になる。 テストカバレッジ(網羅率)とソフトウェア品質 単体テストでは網羅率という指標がよく使われます。全体のソースコードに対してどれだけがテストされたかを見る指標になります。 コード網羅率 = 実行されたコードの行数 / 総行数 (0-100%の範囲で算出) 数値化された指標は、全体を把握する上で必要ですが、数値だけに頼りすぎるとテストの質(中身)を見誤ってしまいます。 単体テストの完了条件として「C0/C1カバレッジ100%」となっているプロジェクトを見かけます。カバレッジが高ければ、ソースコードの品質が高いと言えるでしょうか。カバレッジが100%でも、テストケースが正しく作成されていなければ、バグが潜在している可能性を低くすることはできません。バグを適切に検出できるテストケースを作るにはスキルが必要です。 では、バグを適切に検出できずに潜在させてしまうテストケースとはどのようなものなのでしょうか。「Google Testing Blog: TotT: Understanding Your Coverage Data」も参考にアンチパターンをいくつか考えてみましょう。 アンチパターンその1   配列のインデックス範囲外アクセス java int[ ] array = new int[5]; int value = array[5]; // インデックス5は範囲外 テストケースがarray[0]からarray[4]までのインデックスをテストしている場合、C1カバレッジは100%になりますが、インデックス5にアクセスするテストケースがないと、配列の範囲外アクセスによるバグを見逃すことになります。 アンチパターンその2   null参照の処理 java String str = null; int length = str.length(); // null参照によるNullPointerException strが非nullの状態でのテストケースのみを実施していると、C1カバレッジは100%になりますが、strがnullの場合のテストケースがないと、NullPointerExceptionを引き起こすバグを見逃すことになります。 アンチパターンその3  条件分岐の境界値 java int score = 85; if (score >= 90) {     // A評価 } else if (score >= 80) {     // B評価 } scoreが85の場合のテストケースだけを実施していると、C1カバレッジは100%になりますが、境界値である90未満や80未満のテストケースがないと、評価のロジックに潜むバグを見逃すことになります。 これらの例は、テストケースが特定の条件や境界値に対して不十分である場合に、潜在的なバグを見逃すリスクを示しています。テスト設計においては、さまざまな入力や条件を考慮する必要があります。 良い単体テストとは さて、良い単体テストとは、どんなものなのでしょう。Vladimir Khorikovは「Unit Testing Principles、 Practices、and Patterns」にて、次のように述べています。(「単体テストの考え方/使い方 」 2022 須田智之 訳) 良い単体テストとは、ソフトウェア開発プロジェクトを持続可能なものにすること。本書では、コードを資産ではなく、負の遺産として捉えています。プロダクションコードのコードベースに何らかの変更を加えることは、コードベースのエントロピー(無秩序の量)を増やします。コードの整理やリファクタリングをなどの適切な処置を常にしていなければ、そのソフトウェアはすぐに複雑になり秩序がなくなってしまいます。そうなると1つのバグを修正することが、より多くのバグを生み出すことになったり、他の部分が機能しなくなったり、ドミノが次々と倒れる状況に陥ります。しかし、テストを用意しておけば、それを防げます。テストがあることで、コードによる退行(regression)を検出することができるのです。 「単体テストの考え方/使い方 」 2022 須田智之 訳 本書では、良い単体テストについて以下のことが提案されています。  ・プロダクションコードのリファクタリングに伴って、テストコードをリファクタリングすること ・プロダクションコードを変更するたびにテストを実施すること ・テストが間違って失敗した際にその対処をすること ・プロダクションコードの振る舞いを理解するためにテストコードを読むこと コードが増えれば、ソフトウェアにバグが持ち込まれる経路が増えることになり、プロジェクトを維持するコストもさらに高くなる。この問題を解決するためには、コードを最小限にすべきである。テストコードも同様でバグに対して脆弱であり、保守を必要とするものである。 「単体テストの考え方/使い方 」 2022 須田智之 訳 さて、どの様にテストの質をあげればいいのでしょう。何を単体と見做すかは、それぞれのプロジェクトによって様々だと思いますが、単体テストにおける「単体」を1単位のコードでなく1単位の振る舞いにするよう推奨されています。そして、テストケースを1つずつ評価して、本当に必要なテストケースと不必要なケースを識別して、テストスイートには必要なケースのみを残して、他のテストケースは削除する作業が必要です。優れたテストスイートとは次のようなものです。 テストが開発サイクルに組み込まれている コードベースの特に重要な部分のみがテスト対象になっている 最小限の保守コストで最大限の価値を生み出すようになっている コードベースのすべての部分が単体テストをする価値を持っているわけではありません。ほとんどのアプリケーションにおいて核となる部分はビジネス・ロジックを含む部分です。テストに費やした時間が最も効果的な箇所に重きを置いてテストするべきです。因みに重要でないコード ※2 とは次の様なものです。 インフラに関するコード 外部サービスや依存関係のあるもの(データベースやサードパーティーのシステム) 構成要素同士を結び付けるコード ※2 例に挙げたコードは、単体テストのフェーズでは、優先度は低いため重要でないコードと表現しましたが、これらの部分は統合テストや結合テスト、またはエンドツーエンド(E2E)テストなどで十分に検証する必要があります。 では、単体テストの良しあしをQA視点では、どのように見るのでしょうか。ソフトウェアの品質保証は、各テストフェーズの断面で保証する部分とトータルで保証する部分があります。単体テストでは、ひとつの振る舞いを検証しますが、システムの外部品質の保証は出来ません。少なくとも言えることは、単体テストにビジネスロジックの観点が網羅されている。間違った理由でテストに失敗することが少ない。テストに時間がかかりすぎていない。かの確認はレビューしましょう。テストフェーズは、結合テスト、統合テスト(システムテスト)、運用テストと続きます。単体テストで担保するもの、その後のテストフェーズで確認すればいいものを識別して、テストフェーズのトータルでソフトウェアの品質を高めていきましょう。 さいごに 本投稿では、単体テストについての考え方を紹介しました。カバレッジは、意味がないとまではいいませんが、たとえ単体テストのカバレッジ100%を達成したとしても、ソフトウェア品質が保証されたわけではありません。実際の品質保証にはテストの内容と深さを考慮する必要があります。皆さんがそれぞれ現場で実践してみて下さい。 最後まで読んでくださってありがとうございました。 出典 「ソフトウェア品質を高める開発者テスト」高橋寿一著 翔泳社 「単体テストの考え方/使い方 」 Vladimir Khorikov, 須田智之 マイナビ出版 「Unit Testing Principles、 Practices、and Patterns」Vladimir Khorikov (著) 参考情報 「Google Testing Blog: TotT: Understanding Your Coverage Data」 The post 単体テストについて ~テストの質を考えてみた~ first appeared on Sqripts .
アバター
帰納的な推論 と 発見的な推論(アブダクション) は、 私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。 それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意すると質の高い思考ができるのか、基本知識を押さえておくと実務のレベルアップにつながります。 【第1回】見つけるための論理|実務三年目からの発見力と仮説力 帰納的な推論 と 発見的な推論(アブダクション) は、私たちがソフトウェア開発の現場/実務で(知らず知らずにでも)駆使している思考の形です(それどころか日々の暮らしでも使っています)。それほど“自然な”思考の形ですが、どんな考え方で、どんなところに注意す...  続きを読む  Sqripts 関連記事|Sqripts 今回からしばらくは、 帰納的な推論 の考え方を見ていきます。 今回は帰納的な推論の“おさらい”と、いくつかある「形」の紹介です。 帰納的な推論とは 共通項を見つけて一般化する 図2-1 帰納的な推論 図2-1は、以下の特徴を持つ帰納的な推論の例です。 一般化 (A)(B)とも、有限個の 事例に“共通項” (共通する属性、特徴、法則性、etc.)を見出し、 「夕焼けが見られた日」全体や「着飾って出かけた場合」全体に 一般化 しています。 蓋然的 (A)は過去に観測した天候、(B)は自身の過去経験という 有限個の事例から全体に 話を広げており、“間違い”の可能性を含みます。 (当てはまらない場合を見落としている、未来の新たな事例には当てはまらないかも知れない、etc.) “ 共通項 ”とは次のようなものごとを指します。「見てすぐわかる」ものばかりでないこともあります。 共通する属性、特徴。 「事例にはすべてAという属性や特徴が見られる」 共通する法則性(相関関係、因果関係、etc.)。 「事例がPという属性/特徴を持っている時は、必ずQという属性/特徴も具えている」 「事例にPという事象があった場合、必ずQという事象を生じている」 法則性については、「共通している」からといって本当に関係があるかどうかは深く調べないと判らない点に留意しましょう(隠れた要因が存在する「擬似相関」かも知れませんし、「偶然の一致」であることもあり得ます)。 一般化の原理 帰納的な推論では、前提と結論との間に必然的な関連がない以上、事例や一般化される共通項には“納得感”――「確かに共通しているものがある」「確かにすべての場合に言えそうだ」と思えることが求められます。 前提で取り上げる事例が恣意的なものでないなら、納得感は強い (対象全体から偏りなく選ばれたものなら、なお好ましい) 共通項は事例にとって偶然的なものでなく、本質的・必然的な関連があると、納得感は強い 後者の「本質的・必然的な関連」には 自然の斉一性 や 因果性 が根拠になります(どちらも、私たちが知らず知らず当てにしている考え方です)。 自然の斉一性 :自然現象には法則性があり、同じ現象は、同じ条件の下でなら同じように起こる、と見る考え 因果性 :ある現象/性質/属性/特徴/etc. には、それを生じさせた原因がある、とする考え 図2-1の例では、(A)は過去何度も観測した出来事を事例としており、偏りも小さそうです。見出した「法則」は自然現象として因果関係が説明可能で、“納得感”は強いでしょう。 (B)は、事例に偏りはないかも知れませんが、数が気になる(少ないのでは?)ほか、印象が強かったことを選択的に記憶している可能性があります (たとえば、デートでは雨に降られたことがないが、それがいつものことなので記憶に残っていないのかも知れない)。 また、「着飾って外出すること」と「雨に降られる」こととの間には、(A)ほどの必然的な関連はないでしょう。 (A)に比べると“納得感”は弱いと言えます。 帰納的推論の形 事例を挙げて、共通項を見出し、対象全体に一般化する筋道にはいくつかの考え方があります。 次の章から見ていきましょう。 完全枚挙 ――事例をすべて列挙する 有限の事例をすべて列挙 し、それらの共通項を一般化することを 枚挙的完全帰納法 といいます。 図2-2 すべて列挙し、“一般化”する 形は帰納的な推論ですが、「一般化」の観点からすると帰納らしくありません。 対象の事例を 全網羅 できたなら、それは 「全称判断の演繹的推論」と同じ と言えます 「すべての事例には共通項Pがある。従って、すべての事例には共通項Pがある」と 言っているわけで、 一般化も何も「判っていることを言い直している」に過ぎず、 前提から結論に何の飛躍もなく、「新たな発見」も感じられません 以上から、帰納的推論である意味が薄いと言えます。 枚挙的帰納 ――帰納的推論の“基本形” 有限の不完全な列挙から結論を導く 図2-3 枚挙的帰納の例 図2-3の(A), (B)とも、 有限の事例の列挙 から 共通項 を見出し、それを 一般化 して: (A)では「入力欄はすべてある特殊文字を入力した時にフリーズする(すべての事例は共通項Pを持つ)」という結論を、 (B)では「ソフトウェアXは、ソフトウェアZがプリインストールされている機種なら必ず故障Fを起こす(すべての事例において、共通項Pを持つものは必ず共通項Qを持つ)」 という結論を、 それぞれ引き出しています。 このような、有限の不完全な列挙から結論を導くものを「 枚挙的帰納 」といい、帰納的推論の基本的な形です。 蓋然性の度合い 帰納的推論の蓋然性(結論が当てはまる確からしさ)の度合いは、前提で挙げられる事例の質と量に依存します(参考:『論理学入門』)。 ① 事例の数 。多い方が結論の蓋然性は高い ② 事例どうしの類似性 。 互いの共通点が多い方が蓋然性は高い ③ 事例の多様性 。事例の数が多いならば、 事例間の類似性が低い(多様性が高い)方が蓋然性は高い 「③多様な(偏りのない)事例を、①多く集めた上で、②なお類似点が多いなら、蓋然性はより高い」ということです。 (「一般化の原理」の節も参照してください) 図2-3の(A)では、「入力欄(入力項目)」「特殊文字」という類似性があります(②)。 10箇所が多いか少ないかは議論の余地がありますが(①)、 テスト視点でなら「疑うには十分」と感じる人が多いでしょう。 (「調べ過ぎ」と感じる人もいると思います。何個遭遇したら「怪しい!」と思うか、アンケートを取ってみたいですね) (B)では、テスト用に保有しているいちごフォンのバリエーションという類似性と多様性があります(②③)。 (世の中に実際に存在するバリエーションをすべて揃えることは現実的に困難なので、代表的なもの、最も普及しているものなどを中心に揃えることが多いでしょう) なお、どちらの例でも、得られた結論はいわば「仮説」であり、その正しさを評価するにはさらに事例を調べたり、実験したり、詳しく論証したりする必要があります。 評価した結果、「実際にはそうでなかった」という、“間違った”推論と判明する可能性があります。 統計的帰納 割合や傾向を推論する 事例に見てとれる“共通項”の割合/傾向を踏まえて、 対象全体の中で 共通項を持つものの 割合 や 傾向 を推論する、という形があります。 図2-4 統計的に推論したい 図2-4では、同じクラスの生徒が特定の機種のスマートフォンを所持する割合から、「学校全体」における所持の傾向を推し量っています。 クラスの中での所持割合を学校全体に広げて考えても相当程度に蓋然性があるだろう、と、A子さんは主張したいわけですね。 もっとも、事例における割合や傾向を全体に広げて考えてよいかどうかは以下の点にかかっています。 事例の数(=標本の大きさ)。母集団(対象全体)の大きさに対してある程度の大きさであること 事例のランダムさ(=偏りのなさ)。母集団の特徴/傾向を適切に反映していること 図2-4の例でいうと、1クラス40人という事例の数は、学校全体(数百人はいるでしょう)に対して蓋然性の精度を担保するにはやや物足りません。(無意味ではありません) 事例のランダムさ(偏りのなさ)については、A子さんのクラスの構成や傾向(男女比、機種の好み、etc.)が学校全体に比して偏りがなく平均的なら、学校の生徒全体の傾向と同じと考えやすく、A子さんの推論は蓋然性が高いと言えるでしょう。 そうでなく、学校の生徒全体の構成や傾向に比してクラスのそれが偏っているなら、A子さんの主張は“弱く”なるでしょう(学校全体に対して、A子さんのクラスはいちごフォン好きが異様に多い、など)。 統計の話は本連載の範囲を超えるのでこれ以上踏み込みませんが、統計的な推論の蓋然性を高めるなら、事例の数とランダムさは母集団の大きさに対して適切に定めるのが望ましいと言えます。 統計的一般化 図2-4のA子さんのように、統計的な前提をもとに「全体」へと話を広げるのは 統計的一般化 と呼ばれます。 「事例において、共通項Pを持つものの割合がこうである」から、「対象全体でも、割合はこうである」と一般化します。 統計的一般化の例。 ①この学校の生徒から相当数を無作為に選び、所有するスマートフォンを尋ねたところ、 90%がいちごフォンを所有していた。 ②【結論(A)】この学校の生徒(の90%)はいちごフォンを所有している。 ②【結論(B)】この学校の生徒は(おそらく)いちごフォンを所有しているだろう。 結論(A)は事例における割合を結論に引き継ぐ形、(B)は推量として表現する形です。 (B)の場合、割合が90%なら「きっといちごフォンを所有しているに違いない」という言い方もあるでしょう。 100%なら「いちごフォンを所有している」と断言したくなるかも知れません。 割合が高ければ結論の蓋然性も高いと見込まれ、“納得感”はあります。 そうでなければ“納得感”は弱いでしょう。 割合が50%程度か未満なのに「おそらくいちごフォンユーザーだろう」というのは無理があります。 また、事例における割合が100%であっても、対象全体における実際の割合は100%でないこともあります。 図2-5 統計的一般化 枚挙的帰納とは事例の数と偏りの点で異なる点に注意してください。 枚挙的帰納の例。 ①回りの友達に聞いたら、BさんもCさんもDくんもEくんもFさんもGくんも、全員いちごフォンを持っている。 ②だからこの学校の生徒はいちごフォンを所有している。 統計的三段論法 統計的帰納を用いて、演繹的な定言三段論法に似た形の推論ができます。 統計的三段論法の例。 ①この学校の生徒の90%は、いちごフォンを所有している。 ②いまこの場所にいる生徒は皆この学校の生徒である。 ③【結論(A)】ここにいる生徒(の90%)はいちごフォンを持っている。 ③【結論(B)】ここにいる生徒は(おそらく)いちごフォンを持っている。 結論(A), (B)は先の統計的一般化と同様です。 (余談ながら、この例は 論理スキル[実践編]・ソクラテスは電気羊の夢を見るか?(前編) で紹介した 定言三段論法の第1格 の形ですね) ソクラテスは電気羊の夢を見るか? (前編)|テストエンジニアのための論理スキル[実践編] テストエンジニアが身につけておきたいスキルの一つ「論理のスキル」。「論理の言葉」の意味や働きに注意が向くようになったら、文や文章の読み書きで実践していきましょう。この連載では、「論理スキル“実践編”」と題して、「文章の筋道を把握する、主張を理解する...  続きを読む  Sqripts 関連記事|Sqripts 結論の蓋然性が前提における共通項の割合に依存するのは統計的一般化と同様です。 図2-6 統計的三段論法 レッツ帰納的推論 帰納的な推論には、他に 類推(類比推論) や 因果関係からの推論 という仲間がいますが、これらについては回を改めて紹介したいと思います。 ★ 枚挙的帰納や統計的帰納のような思考は、私たちが日ごろ仕事や私生活で(なんとなくでも、知らず知らずでも)行なっている形の推論で、特別・特殊なものではありません。 (統計的な帰納を自分で行なうことは少ないかも知れませんが、ニュースなどで頻繁に見る「アンケート調査」はその好例です) 帰納的推論は“間違い”の可能性を孕む推論ですが、それは手順のミスや不注意などによるのではなく、形式上避けることのできないものです。“間違い”に臆さず「新たな発見」に邁進しましょう。 次回は、帰納的推論をする上で参考になる考え方・進め方を紹介します。 参考文献 近藤洋逸, 好並英司 『論理学入門』 岩波書店 1979 鈴木美佐子 『論理的思考の技法Ⅱ』 法学書院 2008 藤野登 『論理学 伝統的形式論理学』 内田老鶴圃 1968 図版に使用した画像の出典 Loose Drawing 人物画をお借りしています。 品質探偵コニャン:Produced by Sqripts . No Unauthorized Reproduction. ソクラテスは電気羊の夢を見るか? (前編)|テストエンジニアのための論理スキル[実践編] テストエンジニアが身につけておきたいスキルの一つ「論理のスキル」。「論理の言葉」の意味や働きに注意が向くようになったら、文や文章の読み書きで実践していきましょう。この連載では、「論理スキル“実践編”」と題して、「文章の筋道を把握する、主張を理解する...  続きを読む  Sqripts 関連記事|Sqripts The post 【第2回】 “共通項”を見つけ出す|実務三年目からの発見力と仮説力 first appeared on Sqripts .
アバター
この連載では、ソフトウェア開発のQAエンジニアとして働き始めた皆様に向けて、私の実体験をもとに「こんなことを知っておけばよかった」という、ちょっとした気づきを共有します。 一緒にソフトウェア開発のQAエンジニアとしての充実したエンジニアライフを築くためのヒントを探っていきましょう。 <QAエンジニアのスタートガイド 記事一覧> ※クリックで開きます 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- QAエンジニアは開発・テスト・運用など、さまざまな場面で活躍しています。そんな中でも「ソフトウェアテスト」は外せない要素だと思います。 QAエンジニアになりたての頃は、ソフトウェアテストの「テスト実行」を任されることも多いと思います。そういった状況で「テスト実行はつまらない」と思っている人もいるかもしれません。それはもったいないことだと私は思っています。 実際のところ、「テスト実行」はテストプロセスの中で最も大切な活動であり、プロジェクトへの貢献はもちろん、学びや楽しみの多い活動でもあります。 「ソフトウェアテスト」を解説する記事として、第3話では「テスト実行」について取り上げます。 テストに似た用語として、「試験」「検査」「検証」「評価」といった言葉が使われることがありますが、ここでは「実際の製品を動かしてその結果を観察する作業」を「テスト」としています。また、JSTQBなどを勉強したことのある方は「静的テスト」と「動的テスト」という言葉を聞いたことがあるかもしれません。本記事では記載のない限り、「動的テスト」について扱います。 テスト実行はソフトウェアテストの華である テスト実行へのよくある誤解 「テスト実行」という活動はビギナーにも割り当てられやすいタスクです。 使用する際に資格や特殊な技能が必要のないような製品では、実際にソフトウェアを動かす人として、一般的なユーザーを想定している場合が多いです。 あるいは、製品の仕様のキャッチアップのために、テストエンジニアに限らず新規参入の人がテスト実行にアサインされる場合もあります。 そのために、テスト実行について以下のような印象を持っている場合があります。 テスト実行はテストケースを消化する単純作業でつまらない仕事だ テスト実行は簡単な作業だから学べることは少ない テスト実行は誰でもできるからテスト実行者はスキルがない これらの印象から「テスト実行」というタスクを拒否するQAエンジニアにも出会ったことがあります。私はテスト実行に対してこういった印象を持たれることを残念に思いますし、誤解であると思っています。 テスト実行は重要な活動である テストプロセスの中でのテスト実行 ソフトウェアテストは、テスト活動の開始から終わりまでプロセスで表現できるという考えが一般的です。これを「テストプロセス」といいます。 テスト実行はテストプロセスの中で最も重要なプロセスであると考えています。 たとえばJSTQBでは、テスト計画、テスト分析、テスト設計、テスト実装、テスト実行、テスト完了、テストのモニタリングとコントロールといった活動が識別されています。 ※上記の図において、「テストのモニタリングとコントロール」については、「テスト計画を含む」という考えで記載しています。2018年などの従来のシラバスではモニタリングとコントロールにはテスト計画を含まない形で定義されていました。一方、2023年に発行された最新のシラバスでは「checking of all test activities」とされており、テスト計画を含むとも読み取れます。 これらすべての活動を行うことがベストプラクティスと言われていますが、そうでないプロジェクトも存在します。たとえば「テスト分析」や「テスト実装」を行っていないプロジェクトも存在します。 一方で、「テスト実行」がないプロジェクトを(プロジェクトが中止しない限りは)見たことがありません。 これらの活動のうち、テスト計画・テスト分析・テスト設計・テスト実装は、あえて一言で表せばテスト実行の準備をしているとも表現できると考えます。 テスト完了についても、そもそもテスト実行が実施されていなければ完了できません。テスト実行結果を元に、報告や学びの蓄積や保守への移行など、さまざまな完了作業を行います。 !注意! この文章を読み、「テスト活動はテスト実行の準備をしている”だけ”」と片付けるのは少し乱暴です。 テスト計画ではステークホルダーとの合意形成を行う大切な活動です。また、テスト分析やテスト設計は、開発の資料にフィードバックする活動につながることもあります。 こういったテスト実行以外への効果は、この連載で書ききれないほどたくさんあります。 テスト完了についても「テスト実行結果”だけ”がテスト完了のインプットになる」と思ってしまうと少し誤解があります。実際はテストプロセス全般を通じて得られた情報のレポーティングや学びの蓄積を行います。 テスト実行を考えない成果物は取り扱いが難しい テスト実行は後工程であるので、テスト実行について考えることを一旦棚上げして、テスト計画やテスト設計を行う場合もあります。しかし、それはアンチパターンだと考えます。 「計画したテストがいつ・どのように実行されるのか」「設計したテストを実現するためにどうすれば実行できるのか」など、テスト実行についてきちんと考えた上で活動することが大切です。 テスト実行について検討できていないテスト計画やテスト設計は、テスト実装やテスト実行のフェーズで大きな負担になったり、場合によっては手戻りや追加のコストがかかってしまう場合があります。 テスト実行によって「事実を積み重ねる」ことが大切 テストプロセスにおいて、テスト計画からテスト実装は「想定を積み重ねている」にすぎないと考えます。 「お客様に品質を保証する」と考えた時に、私は「事実をきちんと把握できているかどうか」が大切だと考えています。 予測や想定ではなく、「こんな状況でソフトウェアはこんな動作をした」という事実を積み重ねることで、我々は自信を持ってお客様に製品を届けられると考えています。 事実を積み重ねることができる重要な活動が「テスト実行」なのです。 テスト実行の仕事を充実させるポイント アイデアを言語化したり実際に試す テスト実行をするにあたって、目の前のテストケースを思考停止で消化していることがあるかもしれません。それはQAエンジニアとしてもったいないことをしています。テスト実行の際には思考を停止するのではなく、むしろ思考を活性化させてほしいです。 ポイントは様々な発想を広げることです。たとえば以下のような疑問を持つことが有効だと考えます。 こういった動作で顧客はどんな風に感じるだろうか? こんな都合の悪い操作を行ったらどんな動作をするだろうか? 似たような製品ではどのような動作をしているだろうか? これらについて実際に試す際には「言語化すること」もおすすめします。チケットを起票するときや、テスト分析をするときには、こうした言語化の技術が仕事の質やエンジニアとしての実力差に繋がると思います。 「言語化を考える以前にテスト実行進捗に対する圧力がある」ということもあると思います。 その場合は、ぜひテストの準備やテスト実行自体を効率よくできるように検討してください。 たとえばテストの準備・調達の手順が不明確だったり、テスト実行手順が非効率な場合があるかもしれません。もしかしたら自動化を行う余地があるかもしれません。 テスト実行という活動には創意工夫を行う余地があることはもちろんですが、テスト実行の場合、最も工数がかかる活動であるということもあり、改善の効果が得られやすいことがあります。 テストそのものやテストケースの目的に思いを馳せる テスト実行は学びが少ないと思われがちかもしれませんが、学習の材料は大量に存在します。 テストケースやテスト計画書などです。それらの成果物からテスト設計の意図やテストの存在意義について考えてみてください。 もしテストをしていて「このテストケースは無駄だな」と思われるなら、そういった考えの言語化に挑戦することをおすすめします。「無駄なテストを省く」「そのためにきちんと説明できる」というのはテストマネージャーやテスト設計者として必須のスキルになります。 これらはテスト実行を行いながら考えることができます。 テスト実行の専門性を高める テスト実行は誰でもできると思われがちですが、テスト実行にも専門性があります。不具合発生時のチケットでの報告や切り分けには、慣れや経験があります。これらは学習によってもキャッチアップできますが、バグというのは多種多様で、経験や感覚に頼る部分も多いのが現状です。 そのため、テスト実行を通して、よりよいテスト実行者になることも有意義だと考えます。 おわりに 本記事では「テスト実行」について充実させるためのポイントを紹介しました。 テスト実行を通してテストに関するさまざまなことを学んで欲しいと思います。 また、将来キャリアアップしたときに、テスト実行ができないポジションとなる可能性もあります。その時に「テスト実行での学びをするのを疎かにしていた」ということがないようにしてほしいと思います。 続く後編では、テスト実行以外の活動にフォーカスを当て、解説していきます。 【連載】QAエンジニアのスタートガイド 記事一覧 【第1回】充実したQAエンジニアとしてスタートするためのガイドライン 【第2回】「誰のためか」を意識しよう 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編- The post 【第3回】QAエンジニアの第一歩、「ソフトウェアテスト」を知ろう -前編-|QAエンジニアのスタートガイド first appeared on Sqripts .
アバター
この連載では、1人目QAとしてのチームの立ち上げや組織づくりに関して、私が実践したことや試行錯誤中のことも含めてお伝えします。 前回の記事 では、チームビルディングの概念や考え方の説明と、QAチームにおけるチームビルディングについてタックマンモデルの各段階をもとに概要をご紹介しました。 今回は、QAと開発者という、異なるロール間でのコミュニケーションについてご紹介します。 コミュニケーションというと非常に広い話になりますし、開発者とQAの関わり方や組織の形なども会社によっていろいろな形があります。ただ、私が他社のQAの方から「開発者とのコミュニケーションに課題があって・・・」と相談をいただいて話を聞くと、いくつかのパターンとそれに対する基本的な対応方法があるように感じています。 そこで、この記事ではQAと開発者とのコミュニケーションに関してよく聞く課題と、とくにQAと組織を立ち上げていく過程で気をつけるべきことについてご紹介します。 QAと開発者とのコミュニケーションにおける課題 QAにとって、開発者との関係性というのは非常に大切です。これは実際にQAとして働いている方にはほぼ確実に同意していただけるのではないでしょうか。 QAだけががんばってもプロダクトの品質向上には限界があり、開発者やマネージャー、デザイナーなど他のさまざまなロールの方と協力して初めて品質を高められます。特にQAが業務レベルで関わるのは開発者である場合が多いはずです。 そのため、開発者との関係性がよければ互いに協力して品質を高めることができますし、逆に関係性が悪いとなかなか同じ方向を向けず品質にも悪影響があります。最近よく聞く言葉で言えば、開発者とQAが協調するとか、互いにロールの垣根を越えて(越境して)働くとか、そういった動き方が良しとされていますね。 こうした理想の姿については、それほど反対されることはないかと思います。 しかし、実際に現場でQAとして働いている方の話を聞くと、開発者とQAとの間のコミュニケーションについていろいろな問題があるようです。 たとえば、技術面で開発者とコミュニケーションが取りづらい、品質に対する温度感の違いがある、QAに対してネガティブなイメージを持たれている、などです。そうした問題をいろいろな方から聞いた中で、大きく以下2つの要素が多く出てくると気づきました。 QAエンジニアの役割や業務が開発者側に伝わっていない コミュニケーションの土台が不足し、開発者体験が悪化している それぞれについて、どのように対応すればよいのか考えていきましょう。 QAの役割や業務に対する理解を得る ひとつめは、QAの役割や業務が開発者側に伝わっていないという問題に対する対応です。これは単純に問題の裏返しで、QAの役割や業務に対して理解を得ましょう、という話です。 とくにQA組織をこれから立ち上げる場合はQA組織の位置づけ、どのような役割を担うのか(それによって開発者の動きがどう変わるのか)などが明確になっていないと、すれ違いが発生します。 よく聞く具体的なお悩みとしては、大きく2パターンです。 品質に対する考え方に関するもの 開発者が「テストはQA・テストエンジニア側のしごと」と考えている 品質に対する開発者の意識が低い、大事だと思ってくれていない など QAの役割・動き方に関するもの QAが居ると開発スピードが遅くなる、と思われている 重要でない細かい指摘をたくさんされると思われている など これらの開発者からQAに対する誤解については、ていねいに説明をして理解を得ていくことが大切です。 方法1:QAがやること・やらないことの宣言 これは私が事あるごとにオススメしている方法なのですが、その組織の中でQAエンジニアが何をやるのか&何をやらないのかを宣言することで理解してもらう、というものです。 たとえば私は現在のQA組織を立ち上げるにあたって、入社してすぐに「QAが決めた基準を守らせたり、アセスメントやメトリクスなどによる定量目標を強制はしません。品質はQAだけが考えるものではなく全員で考えるもので、合意・納得のないルールには意味がないからです」と宣言をしました。 実際に開発者からは「QAが来ると聞いていろいろ縛りがきつくなるのかと思ったけれど、最初に無理やりルールを押し付けないと聞いて安心した。協力できそうだと思った」というフィードバックをもらいました。 一般に「QAがやること」を明確にすることは行われますが、「QAがやらないこと」もセットで伝えることで、開発者にとっての安心につながり、QAに対する意識や見方がポジティブな方向に変わることもあります。 方法2:開発者も含めた全員が品質に対して関係していることを伝える 最近では少なくなってきているように感じますが、「テストはQAに任せておけばいい、品質を考えるのはQAの仕事」といった認識が開発者にあって困っている、という声を聞くこともあります。 この場合は、開発者も含め全員が品質に関係していると理解してもらう必要があります。世の中のQA担当者はさまざまな方法で開発者にアプローチしていますが、たとえばコストに関する以下の図はよく用いられています。 引用:ソフトウェア品質保証の 方法論、技法、その変遷 ~先達の知恵に学ぶ ~ P31より つまり、テスト工程でQAやテストエンジニアが問題を見つけるよりも、コーディング時や設計段階などで問題を見つけたほうがプロジェクトにとっては低コストで済む、ということです。そのため、問題はテスト工程で見つければいいやではなく、開発者も積極的に品質に関する活動やテストを行うべきである、という理屈です。 他にも、体重計とダイエットのメタファを用いることもあります。 ダイエットをしているとき、体重計に乗れば現在の体重がわかりますが、体重計に乗ること自体にダイエット効果はありません。そこでわかった体重をもとに、運動をしたり、食事を見直したりといった行動を起こして初めて体重が減少します。 品質もこれと同じで、テストをすることで現在の品質やどこにバグがあるか等がわかります。しかし、何度テストをしても品質はよくなりません。見つかったバグを修正することで初めて、品質が良くなるのです。 QAやテストエンジニアがいくらテストをしたとしても直接品質を高めることにはならず、開発者によるバグ修正が必要です。つまり、開発者も品質に十分関係している、という理屈です。 ちなみにこのメタファは『ソフトウェアプロジェクトサバイバルガイド』という書籍に登場するそうです。 とくにQA組織の立ち上げ時がカギ とくにQA組織の立ち上げ時というのはこの「理解を得る」もしくは「誤解を解く」ためにとても重要なタイミングです。組織立ち上げに向かって動き始めるタイミングで、QAの役割や業務に関する価値観・大事にしたいことを打ち出していくと、開発者からも「自分たちに協力してくれるんだ」「メリットが期待できるんだ」と感じてもらえ、協力関係が築きやすくなっていくでしょう。 QAに関する理解については以前 【第3回】品質保証やQAエンジニアを知ってもらうための取り組み | Sqripts に記載しましたので、こちらもぜひご覧ください。 【第3回】品質保証やQAエンジニアを知ってもらうための取り組み 1人目QAとしての立ち回り、第3回となる今回は、QAエンジニアや品質保証のことを開発組織に知ってもらうための取り組みについてご紹介します。前回の記事では、1人目のQAは開発組織に対して品質文化を浸透させる役割を求められる、と書きました。しかし、「文化の浸透...  続きを読む  Sqripts 関連記事|Sqripts QAとして信頼を得る もうひとつはコミュニケーションの土台が不足する問題への対応で、ひとつめとも関係しますが、開発者をはじめ他の職種の方から信頼を得ることが大事です。 とくに若手QAの方から相談されることの多いものとして「開発者と技術的な話ができなくて・・・」というものがあります。開発経験がない状態で、テストエンジニアやQAエンジニアになった方だと「開発者が普段話している内容がわからない」「技術的な話についていけない」と感じ、そこから開発者とのコミュニケーションがうまくいっていないと感じることが多いようです。 Developer eXperience Day 2024にて、AtCoder代表取締役社長 高橋直大氏の講演では以下のような内容が話されていました。 開発者体験はチームメンバーによっても決まる 多くのメンバーにとって当たり前のことを知らず、いちいち説明しなければならない状況が発生すると開発者体験が悪くなる 参考: アルゴリズムと開発者体験 – Tech Team Journal 私はこの講演をリアルタイムで聞いていて「なるほど確かに」と感じました。その後、よくよく考えてみると、開発者とQAとの間でのコミュニケーションにおいても同じことが言えると思いはじめました。 開発者とQAとではスキルセットや持っている知識に違いはあるものの、たとえば一般的な開発プロセスや、プログラミングのごく基礎的な内容については双方にとって「当たり前」とみなされる可能性があります。それをQA側が知らず、かつ理解しようという姿勢がない場合は、開発者体験が低下してしまいます。そうなってしまうと、「QAの**さんがいると全体の効率が落ち(たように感じられ)るよね」「品質を高めるうえでは逆効果だよね」と捉えられてもおかしくありません。 では、QAはどこまで何を知っていればいいのでしょうか。この点に関しては絶対の正解はありません。過去の経験上、以下のような内容を把握しておくと開発者とのコミュニケーションの土台になります。 一般的なソフトウェア開発プロセスに関する知識 ウォーターフォールとアジャイル 継続的インテグレーション テスト対象アプリケーションを作るうえでの基礎的な技術 WebアプリケーションであればhtmlとCSS、JavaScriptなどそれぞれの役割と、Web上に公開するまでの流れ モバイルアプリケーションであればXCodeやAndroidStudioでアプリを作って公開するまでの大まかな流れ スクラム関連 各種イベントや用語 チケット管理 BTS/ITSなどを使ったチケット駆動の仕事の進め方 私がよくオススメしているのは、簡単なアプリケーションを作って動かしてみることです。難しいことをする必要はなく、インターネット上で公開されているサンプルや入門書のサンプルを作る流れを1度体験するだけでもかなり違います。 まとめ 今回は、開発者とQAとのコミュニケーションに関する問題やその対応について考えました。 一般的な同僚とのコミュニケーションに関する工夫、たとえば雑談をしたり一緒にランチをしたりといった接触機会を増やす他に、本記事でご紹介したような内容に気を配っていただけるとよいかと思います。 QAを取り巻く環境は、以前に比べるとだいぶ良くなっているように感じます。QAエンジニアという職種の認知も進んできています。そうはいっても、個々のQAが自分の周囲の同僚から理解を得たり、関係性を構築したりといった努力が不要になったわけではありません。 品質向上につながるアクションとして、開発者とのより良いコミュニケーションができるようにしていきたいですね。 【連載】QA組織の立ち上げ方-1人目QAが語る実践と工夫- 記事一覧 【第1回】QA組織立ち上げの流れと組織の形 【連載初回、全文公開中】 【第2回】2人目以降のQAエンジニアの採用 【第3回】QAチームビルディング|QA組織の立ち上げ方 The post 【第4回】QAと開発者とのコミュニケーション|QA組織の立ち上げ方 first appeared on Sqripts .
アバター
こんにちは、フロントエンドエンジニアとして働いているぱやぴです。 これまで主にMantine UIを使って実務を進めてきましたが、最近注目されている「 shadcn/ui 」を試してみました。 本記事では、shadcn/uiの概要やメリット・デメリット、実際に触ってみた感想などを紹介していきます。Mantine UIに慣れている方はもちろん、その他のコンポーネントライブラリを使っている方にも参考になれば幸いです。 shadcn/uiとは? shadcn/ui は、React向けのコンポーネントコレクションであり、UI構築をよりシンプルかつ柔軟にすることを目的としています。主な特徴としては、次の点が挙げられます。 Radix UI のコンポーネントをベースにしている スタイリングは Tailwind CSS を利用 セマンティクスやアクセシビリティ(a11y)を考慮したデザイン 公式サイトからコンポーネントをコピー&ペーストで導入可能 必要なものだけ導入しやすい疎結合な設計 ビルド済みのコンポーネントを導入するのではなく、プロジェクト内に ソースコードとして取り込む 形式が採用されています。 後述するメリットにも大きく関係しますが、この方針によって細かいカスタマイズやアップデートに柔軟に対応しやすくなっています。 メリット 1. Radix UI由来のUIパターン & アクセシビリティ shadcn/uiは Radix UI をベースとしており、アクセシビリティ(a11y)を重視したUIコンポーネントが揃っています。以下の点がメリットです。 UIパターン Tailwind CSSと統合されており、UIデザインを簡単に適用可能 モダンなUIパターンを利用しつつ、ゼロからのデザイン構築の手間を軽減 アクセシビリティ WAI-ARIAのベストプラクティスが適用されているため、デザインを変更してもa11yが担保される キーボード操作やスクリーンリーダーへの対応が優れている 必要に応じてデザインシステムやスタイルを柔軟に追加可能 2. Tailwind CSSとの親和性 & 高いカスタマイズ性 shadcn/uiは Tailwind CSS でスタイリングされているため、次のような利点があります。 既存のTailwindベースのプロジェクトに組み込みやすい クラス名を直接編集することで、デザインやレイアウトを自由に変更できる また、コンポーネントをnpmパッケージとして利用するのではなく、プロジェクト内に直接ソースコードを取り込むスタイルのため、 必要に応じて自由に修正できる 柔軟さがあります。 結果的に、 プロダクト独自のデザイン要件 や将来的な拡張にも対応しやすい点が非常に魅力的です。 3. CLIやコピー&ペーストで導入が容易 shadcn/uiにはCLIツールが用意されており、以下のようなメリットがあります。 コマンド一つでコンポーネントをローカルに自動生成 コンポーネント名を指定するだけで簡単に追加・削除が可能 また、公式サイトから コピー&ペースト する方法でも導入できるため、初めて触れる場合でもセットアップがわかりやすく、すぐに実装に移れるのがメリットです。 4. v0との連携 v0で生成されたコードは shadcn/ui のコンポーネントを使用しているため、そのままプロジェクトに組み込むことができ、プロトタイピングの速度が大幅に向上します。 また、v0が生成するUIはshadcn/uiに基づいているため、AIを用いながらデザインの一貫性を保つことができます。 以下v0について紹介されていた記事になります。 最近話題のVercel v0 Teamプランを導入してみた!その効果と活用方法を紹介 こんにちは!フロントエンドエンジニアのつかじです。今回は、私たちの開発チームで導入した「Vercelのv0 Teamプラン」について、その魅力や実際に使ってみて感じた効果、そして活用方法を詳しくご紹介します。v0とは?まず、v0についてご存知ない方のために簡単に説...  続きを読む  Sqripts 関連記事|Sqripts 5. オープンソースかつコミュニティ駆動で進化し続ける shadcn/uiは オープンソース として公開され、コミュニティが積極的に開発をサポートしています。 バグ修正や新機能要望への対応が比較的早い デザインやアクセシビリティ強化のプルリクエストが日々取り込まれている そのため、今後も 継続的なアップデート が見込まれ、時代に合わせたUI/UXの改善が期待できます。 デメリット 一方で、shadcn/uiを使うにあたってのデメリットや注意点としては、以下が挙げられます。 コンポーネント更新の手間 npmパッケージとして管理されているライブラリと異なり、shadcn/uiはソースコードを直接取り込む形式です。 新しいバージョンがリリースされた場合は、自分たちで差分を確認しながら更新しなければならないため、 保守コスト が増える可能性があります。 Tailwindベースであること Tailwind CSSでの開発が前提となるため、 Tailwind未経験の場合は慣れが必要 です。 既存プロジェクトに導入するには、ビルドチェーンの調整などが必要になる場合もあるでしょう。 実装責任がより増す コンポーネントをコピーしているとはいえ、 プロジェクト内でコンポーネントとして管理 することになります。 そのため、状況によっては同じコンポーネントなのにバージョン差異が生じるなどのリスクも考慮が必要です。 実際に動かしてみる ここでは、簡単に手順を紹介します。(プロジェクト環境によっては多少異なる場合があります) 詳細な導入方法は 公式ドキュメント を確認してください。 shadcn/uiのCLIで導入 npx shadcn@latest init Tailwind CSSのセットアップ npm install -D tailwindcss@latest autoprefixer@latest Next.js + Tailwind CSSのテンプレートを利用するか、既存プロジェクトであればTailwindの設定ファイル( tailwind.config.js )を用意します。 postcss.config.js や tailwind.config.js を適宜編集し、Tailwindを有効にします。 コンポーネントのインストール shadcn/uiの公式サイトで目的のコンポーネントを選択し、CLIまたはコピー&ペーストでプロジェクトに取り込みます。 今回はサンプルとして button をCLIで取り込みます。 npx shadcn@latest add button 取り込んだコンポーネントは components/ui のようなディレクトリに配置されます。 動作確認 ローカルで開発サーバを起動し、ブラウザ上でUIを確認します。 import { Button } from import { Button } from "./components/ui/button"; export default function App() { return <Button>Click me</Button>; } カスタマイズ T Tailwindのクラスを使って自由にデザインを変更できます。 今回はxsサイズをxsサイズの追加とデフォルトでのボタンの表示を背景色に合わせるようにします。 import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "~/lib/utils"; const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { + default: "bg-background hover:bg-accent hover:text-accent-foreground", + primary: "bg-primary text-primary-foreground shadow hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", }, size: { default: "h-9 px-4 py-2", sm: "h-8 rounded-md px-3 text-xs", lg: "h-10 rounded-md px-8", icon: "h-9 w-9", + xs: "h-7 rounded-md px-2 text-xs", }, }, defaultVariants: { variant: "default", size: "default", }, } ); export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { asChild?: boolean; } const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button"; return ( <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} /> ); } ); Button.displayName = "Button"; export { Button, buttonVariants }; sizeに今回追加した xs を指定します export default function App() { return <Button size="xs">Click me</Button>; } ボタンの色とサイズが変わりました。(わかりやすく変更前のものを並べて表示しています。) 実際に試してみた感想としては、 コンポーネントをコピー&ペーストするだけ で「動くUI」がすぐに生成される点が非常に快適でした。 Mantine UIほどドキュメントが整備されていない印象はありましたが、UIの見せ方や挙動の細かな調整がしやすいので、個人的には プロダクトの独自性を出したいケースに向いている と感じます。 終わりに 今回は、新しく注目されている shadcn/ui について、概要からメリット・デメリット、実際に動かしてみた感想をまとめました。 とても簡単に導入することができ、感動しました。 長らくMantine UIを愛用してきた身としては、UIライブラリを丸ごと導入する手軽さや手厚いドキュメントを維持しつつ、もう少し細かいカスタマイズが欲しい…と感じることもありました。 そんなときにshadcn/uiの「コンポーネントを自前で管理できる」という方針は、とても魅力的に思えました。 今後のプロジェクトでは、 デザイナーや他のエンジニアがどれくらい自由度を求めるか によって、UIフレームワークを選ぶ際の選択肢が増えそうです。アクセシビリティとデザインを両立したい方や、 コンポーネントをより細かく制御したい という方には、ぜひ試してみてはいかがでしょうか。 ここまで読んでいただきありがとうございました。 The post コンポーネントライブラリではない!?「shadcn/ui」を触ってみた first appeared on Sqripts .
アバター