TECH PLAY

AGEST

AGEST の技術ブログ

472

こんにちは。性能テストグループのけんです。( 前回執筆時 まではテストオートメーショングループ配属でしたが、今年度から新たに性能テストグループが爆誕しました) 私が主に担当している性能テストについてあれこれ投稿していきます。 前回までは性能テストの概要やテスト計画について説明しましたが、今回は対象シナリオについて説明していきたいと思います。 <過去記事> #1 性能テストの目的と種類 #2 テスト計画 対象シナリオとは ISTQBのシラバスには性能テストの主要な活動として以下の項目が定義されています。 今回はテスト計画からテスト設計へと足を踏み入れていきます。 性能テストの主要な活動 テスト計画 テストのモニタリングとコントロール テスト分析 テスト設計 テスト実装 テスト実行 テスト完了 参考文献: 「ISTQB テスト技術者資格制度 Foundation Level Specialist シラバス 性能テスト担当者 Version 2018.J01」 性能テストの話をすると、まずどの機能または画面を対象とするのかという議論が自然に出るかと思います。 それを決定したものが対象シナリオになるのですが、もう少し詳しく説明していきます。 運用プロファイルとロードプロファイル 性能テストの対象として選定する画面や機能には、送信されるリクエストとその実行順序があります。 それらのリクエストを組み合わせた一連の流れをISTQBのシラバスでは「 運用プロファイル 」と定義しているように読み取れます。以下がISTQBのシラバスの説明文です。 システムの特定の使用方法について、アプリケーションを通じた再現可能なステップバイステップのフローを提供する。 運用プロファイルとは別に「 ロードプロファイル 」というものも定義されています。 ロードプロファイルは、運用プロファイルを使用してどのように負荷をかけるかを定義することになりますが、今回は詳細な説明については割愛します。 運用プロファイル=対象シナリオ ですが、そもそも「運用プロファイル」という字面だけを見た場合、何を指しているのかわからないですよね。 そのため当社では余計な補足説明が必要となることを避けるため「 対象シナリオ 」と定義しています。 対象シナリオについて、当社では以下の通り説明しています。 「 特定のユーザー操作を模倣して送信されるリクエストの一連の流れです。 」 手前味噌ながら簡潔かつ洗練された文言で定義されていますね。 また、「シナリオ」の前に「対象」という言葉を添えることで、それが性能テストの対象となるシナリオであることを表しており、 シナリオは選定する必要がある という意味も込めています。 対象シナリオの定義 対象シナリオを定義する上で基本方針となるのは、本番の運用でかかる負荷を再現するために、主となるユーザーの操作を模倣することです。 ユーザーがたどる動線からシナリオを作成するために以下を定義していきます。 シナリオ動線 シナリオ詳細 シナリオ動線 シナリオにどのような動線(ページまたは機能など)を含めるべきかを説明していきます。 アクセス量の多いページまたは機能 稼働中のシステムのアクセスログを確認して、アクセス量が多いリクエストを対象とする方法が最も妥当です。 「 アクセス量が多い = 負荷が高い 」となるため性能テストの対象とすべきという考え方です。 稼働前でアクセスログの確認ができない場合は、他の類似システムのデータを調査すると良いそうです。 アクセス量が多いものとしては以下があります。 直接アクセスされるURLリンク フロントとなるトップページやWeb検索でヒットしやすいページなど、外部サイト等からの入口として直接アクセスされるURLリンクのリクエストはアクセス過多になる可能性が高いため、対象にすべきと考えます。 ログイン システムを利用するために必要な動線として、最もよく使われる機能の一つです。 システムの主目的となるページまたは機能 システムの主目的となる機能や、アクセスできなくなることで損失が生じる可能性があるページまたは機能は対象とすべきです。 例としては以下があります。 ECサイトにおける「決済処理」 勤怠管理システムにおける「勤怠入力」 アンケートサイトにおける「アンケート回答送信」 また、基本的にはそこへ至るまでの動線についても同様、対象にすべきと考えます。(例外については後述します) 処理に時間がかかる機能 リクエストの処理に時間がかかる機能またはページは、その処理の完了を待つユーザーにとってはストレスと感じてしまうため、ユーザービリティを満たす性能を担保すべきと考えます。 また、処理しているサーバー側ではCPU使用率が上がって性能が低下するかもしれません。 さらに、サーバーの構成次第では他の主要な機能に影響が出る可能性もあるため、テスト対象にすべきと考えます。 以下は時間がかかる機能または処理とその例です。 機能または処理 例 大量のデータ処理 全件検索 ファイルサイズの大きなデータの処理 ファイルアップロード 複雑な演算処理 リアルタイム集計 ユーザーアクセスが多い時に実行されるバッチ(※) 定期実行バッチ(1時間毎) ※ バッチの実行が他のユーザーのアクセスに影響を及ぼさないかを確認するために対象として挙げていますが、実行時間の調整等で運用回避する方法も模索すべきです。 また、夜間バッチ等はユーザーアクセスが少ない時に実行されることから、性能テストの対象となる場合はバッチ単体のスループット計測が目的となる傾向があります。(趣旨がずれるため詳細説明は割愛します) シナリオ例 例として、ECサイトにおける主目的の機能となる決済処理のシナリオは以下の通りです。 「TOP画面(アクセス量の多いページ)」から「決済(システムの主目的となる機能)」まで一気に進むシナリオになります。 厳密に考えると全てのユーザーが決済完了までの動線を辿るわけではないので、ログインするまでのシナリオやTOP画面のみアクセスするシナリオ等を別途作成して、それぞれのシナリオで負荷量とその実行比率(あるいは割合)を調節する必要があります。 例外 前述のシナリオ例ではユーザー操作を模倣して作成していますが、テストの目的によっては必ずしもそれが正しいやり方とは限りません。 例えば、決済サーバーのスペック変更(プログラム変更なし)に伴う性能テストの場合は、決済処理のみをテストすればよいため、決済のAPIのみを単体のシナリオとして実行することもあります。余計なテストを含めないためには事前に要件を確認することが重要です。 対象外とすべきシナリオの考え方 もし対象シナリオを選定する際に「あれもこれも、あとそれもー」と大量のシナリオを実施することになった場合、負荷生成ツールの自動実行スクリプトの実装や、テスト実行にかかる作業工数が肥大化し、結局のところ期間内に終わりません(泣)ということになってしまう可能性があります。 そうならないためにプロダクトオーナーには最小限のリスクを許容していただいた上で「ムダの撤廃、作業コスト削減、生産性向上、働き方改革」などの大義名分を掲げ、強い使命感を持って対象シナリオを絞り込むための交渉をしてください。 交渉材料としてテスト対象外とすべきシナリオの考え方を説明すると、運用時に起こりうる悲観的な状況を想定し、 目的を満たせないことで起こる損失の度合い で検討すると良いと考えます。 逆に、以下の様な機能については予算、工数の都合によって優先度を下げる、あるいは除外してもよいのではないかと考えます。 機能・処理・ページ 例 使用ユーザー数が少ない機能 管理者機能 性能が低いことで直接的な損失にならない機能 ユーザー退会 類似機能、且つサーバーの同じリソースを使用している 別ページで同じ検索機能 データベースへのアクセスが発生しない静的コンテンツのみのページ 説明・ヘルプページ 付加価値として実装されている、主目的の実行とは直接関係のない機能 履歴・ポイント参照 シナリオ詳細 対象シナリオの動線が決定したら、今度はシナリオの詳細となる以下を定義していきます。 トランザクションの定義 滞留時間の設定 トランザクションの定義 トランザクションについて、ISTQBのシラバスでは以下の様に定義されています。 トランザクションとは、開始時点から1 つ以上のプロセス(リクエスト、操作、操作プロセス)が完了するまでにシステムが実行する一連のアクティビティのことである。 トランザクションの応答時間は、システムの性能を評価する目的で測定することができる。 性能テストでは、この測定値を修正や最適化が必要なコンポーネントを特定するために使う。 要するに、対象シナリオに含まれるリクエスト群の計測対象の範囲を定めたものになります。 例えば1ページビューを1トランザクションと定義した場合、メインとなるリクエストの他にサブのリクエストやリダイレクト、静的コンテンツの取得、機能実行に必要なAPI等が含まれる可能性があり、それら全ての応答結果の合計をレスポンスタイムとして計測します。 負荷生成ツールの制約 JMeterなどの負荷生成ツールを使用する場合、Webブラウザーの挙動を完全には模倣できません。(厳密には同じ様な振る舞いをするようにJMeterにプログラムを実装できる場合もありますが、それはブラウザーの挙動ではなくJMeterの挙動となります。) そのため、WebブラウザーがJavaScriptをダウンロードした場合は必要に応じてJavaScriptのプログラムを自動的に処理して機能を実行しますが、JMeterではJavaScriptのプログラムを処理しないため、JavaScriptをダウンロードするまでの時間のみが計測対象となります。 実際に確認してみると… Webブラウザー(例ではGoogle Chrome)の開発者ツールを開いた状態(F12押下)で本サイトのとあるページを開くと、以下の様に主となるリクエストの他にスタイルシート(CSS)やJavaScript(JS)等の大量の静的コンテンツを取得していることがわかります。 リクエストを一つずつ確認すると、ドメインがGoogleのサイトだったりするものが含まれるので、テストの対象外となるサイトにはアクセスしないように除外する必要があります。 また、クラウドサービスが提供しているストレージサービスに静的コンテンツを格納していてそこから直接取得しているような場合、それはクラウドサービスの性能テストになってしまうため対象外としてもよいという考え方もあります。 例 先ほどのECサイトにおける決済シナリオに対して、ページビュー毎にトランザクションを定義すると以下の通りになります。 ログイン処理とログイン後TOP画面が同じトランザクションになるのは、ログイン処理を実行すると、ログイン完了後にログイン後TOP画面へ自動的に遷移するためです。商品検索処理と決済処理も同様です。 滞留時間の設定 ユーザー操作をある程度模倣するため、ページビュー毎に滞留時間を設けます。 滞留時間の考え方は負荷生成方法によっても検討の余地がある部分ではありますが、1仮想ユーザーの動線の再現性を高めたい場合には、ユーザーが各ページをどのくらいの時間参照しているかを検討した上で設定します。 例えば、TOP画面へのアクセス後にログイン画面へ進む場合はそんなに時間を要しないですが、ログイン画面でログインIDとパスワードを入力する場合は時間がかかる想定です。(一定のユーザーはブラウザーに記憶させる場合があるので一概には言えませんが…) ただ、現実に即した長い滞留時間を設定してしまうと、その分だけ目標負荷量を達成するために仮想ユーザー(スレッド)を大量に作成することになります。 その場合、スレッドの大量生成のために負荷生成用のサーバーを増設しなければいけなくなるケースもあります。 そもそも滞留時間には個人差が大きいことから実のところ正解などないため、現実に即した滞留時間を必ずしも追求していく必要はないと考えます。 また、滞留時間は生成するための負荷量(特に時間あたりの処理時間)に大きく影響するため、負荷量の調節に滞留時間の調整が必要になる場合もあります。 必ず設定すべき滞留時間 実際にシナリオを実行する場合、1仮想ユーザー(スレッド)がシナリオを1回完了した後、また同じシナリオを最初からループ実行します。 正常時は特に問題はないのですが、例えばログインに失敗した場合にそのまま後続の処理を継続させると決済処理に進めなくてエラーが発生するので、ログインに失敗した時点でエラーとしてまた最初からループ実行するように設定しています。 もしエラーになってから次のループを開始するまでの間に滞留時間が設定されていない場合、ゼロタイムでのアクセスとなるためここで負荷が上昇してしまいます。 特に、システムへの負荷が原因で大量の仮想ユーザーがエラーとなった場合、エラーとなった仮想ユーザー全てがシナリオの最初のページへゼロタイムでアクセスしてしまうため、サーバーダウンの原因になってしまう可能性があります。 そのため当社ではシナリオの先頭には必ず滞留時間を設けることをルール化しています。 例 先ほどのECサイトにおける決済シナリオに滞留時間を定義すると以下の様になります。 ループの概念も考慮しました。 以上で対象シナリオ(運用プロファイル)の1つが完成となりました。 この対象シナリオをテスト仕様として提示する場合、当社ではドキュメントに以下の通り記載します。 対象シナリオ詳細:【EC-1】決済シナリオ 識別子 トランザクション 滞留時間(秒) EC-1-01 画面 3.0 EC-1-02 ログイン画面 6.0 EC-1-03 (ログイン処理)ログイン後TOP画面 5.0 EC-1-04 (商品検索処理)商品一覧画面 5.0 EC-1-05 商品詳細画面 5.0 EC-1-06 購入手続画面 3.0 EC-1-07 (決済処理)決済完了画面 5.0 EC-1-08 (ログイン処理)ログイン後TOP画面 5.0 ※ ※ 最後の滞留時間は【EC-1-01】TOP画面を実行する前に設定されます さいごに いかがでしたでしょうか。 今回は対象シナリオ(運用プロファイル)の話ができたので、次は対象シナリオを使ってどのように負荷をかけるのか(ロードプロファイル)の話に入っていきたいと考えています。 今後も性能テストについて深堀りしていきたいと考えていますので、次回記事もよろしくお願いいたします。 The post 性能テストのススメ #3 対象シナリオ(運用プロファイル) first appeared on Sqripts .
アバター
ISO/IEC/IEEE 29119は、ソフトウェアテストに関する国際標準であり、テストプロセスやドキュメントの標準化を目指しています。この標準で最も重要なのは、最初の4つのパートであり、それぞれが異なるテストの側面をカバーしています。本記事では、 ISO/IEC/IEEE 29119の重要な4つのパートについて解説を行います。 ISO/IEC/IEEE 29119の重要な4つのパート ISO/IEC/IEEE 29119の重要な4つのパートは以下の通りです。 Part 1: コンセプトと用語 Part 2: テストプロセス Part 3: テストドキュメント Part 4: テスト技法 それぞれのパートが相互に関連しており、ソフトウェアテストの様々な要素を網羅しています。 以下では、 ISO/IEC/IEEE 29119の各パートについて、より詳細に説明します。 Part 1: コンセプトと用語 Part 1では、ソフトウェアテストに関連する基本的なコンセプトと用語が定義されています。以下に、いくつかの重要な用語を紹介します。 a) テストケース: テスト対象の機能や特性を評価するために設計された、入力値、実行条件、および期待される結果を含む項目。 b) テストスイート: 関連するテストケースの集合。通常、テストスイートは、特定の機能や特性に焦点を当てたり、特定のテストレベルやテストタイプをカバーします。 c) テストレベル: ソフトウェア開発ライフサイクルの異なる段階で実施されるテストの階層。例えば、ユニットテスト、統合テスト、システムテスト、受け入れテストなど。 d) テストタイプ: テストの目的に基づいて分類されたテストのカテゴリ。例えば、機能テスト、性能テスト、セキュリティテスト、互換性テストなど。 Part 2: テストプロセス ISO/IEC/IEEE 29119 Part 2では、ソフトウェアテストプロセスが3つのレイヤーに分けられて規定されています。これらのレイヤーは、組織のテストプロセス、テストマネージメントプロセス、および動的テストプロセスです。以下では、それぞれのレイヤーについて更に詳細に説明します。 1) 組織のテストプロセス: 組織のテストプロセスは、企業全体で適用されるテストに関する方針や戦略を定めるレイヤーです。このレイヤーでは、以下のような活動が行われます。 a) テストポリシーの策定: テストポリシーは、組織のテストに関する基本的な原則や方針を定めた文書です。テストポリシーは、組織の品質管理体系と一致している必要があります。 b) 組織のテスト戦略の策定: 組織のテスト戦略は、組織全体のテストアプローチを定めた文書です。組織のテスト戦略は、テストの目的、範囲、リソース、リスク、スケジュール、および成果物に関する情報を提供します。 2) テストマネージメントプロセス: テストマネージメントプロセスは、プロジェクトレベルでのテスト活動を計画、監督、および制御するレイヤーです。このレイヤーでは、以下のような活動が行われます。 a) テスト計画の策定: テスト計画書は、個別のテストレベルやテストタイプに対する詳細なテスト計画を記述した文書です。テスト環境、テスト技法、テストケースの選択基準、テストスケジュール、リソース、およびリスク管理が含まれます。 b) テスト活動の進捗状況の追跡・評価: テストマネージメントプロセスは、テスト計画に基づいて、テスト活動の進捗状況を追跡し、評価します。これにより、問題点や遅れが早期に特定され、適切な対策が講じられます。 c) テスト終結: テスト活動が完了したら、テスト終結が行われます。テスト終結は、テスト活動の成果物のレビュー、テスト結果の承認、およびテスト環境の解放などが含まれます。また、テスト活動の振り返りが実施され、次のプロジェクトやテスト活動にフィードバックされます。 3) 動的テストプロセス: 動的テストプロセスは、実際にテストケースを実行し、ソフトウェアの品質を評価するレイヤーです。このプロセスは、以下のフェーズに分かれています。 a) テスト設計: このフェーズでは、テスト計画に基づいてテストケースやテストデータが作成されます。また、テスト技法が選択され、テストケースの優先順位が決定されます。 b) テスト環境とテストデータの準備: テスト環境は、テストケースを実行するために必要なハードウェア、ソフトウェア、ネットワーク、およびデータを含む環境です。テスト環境は、テスト計画に従って設定され、適切な構成と制御が行われます。テストデータは、テストに必要になるデータの要件を定義し、準備を行います。 c) テスト実施: テストケースが実行され、テスト結果が記録されるフェーズです。テストの進捗状況や問題点が監視され、必要に応じてテスト計画やテストケースが修正されます。 d) インシデント報告と追跡: テスト活動中に発見されたインシデントは、インシデント報告書に記録され、関係者に報告されます。インシデント報告書には、インシデントの詳細、再現手順、影響範囲、および優先度が記載されます。インシデント報告書は、バグ管理システムに登録され、追跡されます。 これらの3つのレイヤーは、 ISO/IEC/IEEE 29119 Part 2において相互に関連し、ソフトウェアテストプロセス全体を構成しています。各レイヤーは、ソフトウェアの品質を評価し、保証するために、独自の役割と責任を持ちます。 Part 3: テストドキュメント Part 3では、テストに関連するドキュメントのフォーマットや内容が規定されています。以下に、いくつかの重要なドキュメントを紹介します。 a) テストポリシー: 組織のテストに関する基本的な原則や方針を定めた文書。テストポリシーは、組織の品質管理体系と一致している必要があります。 b) テスト戦略: プロジェクト全体のテストアプローチを定めた文書。テスト戦略は、テストの目的、範囲、リソース、リスク、スケジュール、および成果物に関する情報を提供します。 c) テスト計画書: 個別のテストレベルやテストタイプに対する詳細なテスト計画を記述した文書。テスト環境、テスト技法、テストケースの選択基準、テストスケジュール、リソース、およびリスク管理が含まれます。 d) テストケース仕様書: テストケースの詳細を記述した文書。各テストケースには、入力値、実行条件、期待される結果が明記されています。 e) テスト結果報告書: テストの実施結果と評価を記述した文書。テスト結果報告書は、テストの成果物、達成度、品質、および問題点に関する情報を提供します。 Part 4: テスト技法 Part 4では、テストケースの設計に使用されるテスト技法が規定されています。以下に、いくつかの代表的なテスト技法を紹介します。 1) 仕様ベースのテスト技法(ブラックボックステスト技法とも呼ばれる): このアプローチでは、システムやソフトウェアの内部構造や実装を考慮せず、システムの要件や仕様に基づいてテストケースを設計します。この方法は、システムが期待される動作を満たすかどうかを確認するために使用されます。代表的な仕様ベースのテスト技法には、同値分割、境界値分析、および状態遷移テストなどがあります。 2) 構造ベースのテスト技法(ホワイトボックステスト技法とも呼ばれる): このアプローチでは、システムやソフトウェアの内部構造や実装に基づいてテストケースを設計します。この方法は、コードの品質を向上させるために使用され、コードカバレッジやパスカバレッジなどの指標を使って、コードのどの程度がテストされているかを評価します。代表的な構造ベースのテスト技法には、ステートメントカバレッジ、ブランチカバレッジ、および条件カバレッジなどがあります。 3) 経験ベースのテスト技法: 経験ベースのテスト技法は、テスターや開発者の知識、経験、直感に基づいてテストケースを設計するアプローチです。この方法では、過去の問題や欠陥の傾向、およびシステムのリスクを特定するための専門家の知識が活用されます。経験ベースのテスト技法は、エラー推定などのアプローチを含みます。 これらのテスト技法は、単独で使用されることもあれば、組み合わせて使用されることもあります。これらのテスト技法を適切に適用することで、効果的なテストケースを作成し、ソフトウェアの品質を向上させることができます。 まとめ ISO/IEC/IEEE 29119の各パートについて、以下の詳細を説明しました。 Part 1では、テストに関連する基本的なコンセプトと用語を定義し、共通言語を確立します。 Part 2では、テストプロセスの各フェーズを規定し、品質向上と効率化を図ります。 Part 3では、テストに関連する様々なドキュメントのフォーマットや内容を規定し、情報の共有や管理を容易にします。 Part 4では、テストケースの設計に使用される仕様ベースのテスト技法、構造ベースのテスト技法、および経験ベースのテスト技法を規定し、効果的なテストケースの作成が可能になります。 これらの説明を通じて、ISO/IEC/IEEE 29119について理解し、ソフトウェアテストの品質や効率を大幅に向上させることができることを願っています。 ISO/IEC/IEEE 29119とは? 学ぶ理由、メリット、デメリットを分かりやすく解説 The post ISO/IEC/IEEE 29119の重要な4つのパートと各パートの解説 first appeared on Sqripts .
アバター
こんにちは、テスシです。 私はソフトウェア開発で、システムテストに携わっています。この工程では、これまでに開発したプログラムを一つにまとめて、想定通りのものができているかどうかや本番環境でちゃんと動作するかどうかを確認しています。 はじめに 今回のお話は、プロジェクトが進行する中で発生する、環境構築ミスや思い込み(ヒューマンエラー)によるリスケジュールの回避がテーマです。環境はWeb系のある業務アプリで使用するクライアントPCやサーバーのことをイメージしてください。 効率よくテスト活動を進めるには、特にテスト開始直後の手戻り要因となりがちな環境構築ミスやヒューマンエラーといった事前に対処可能なところを十分抑えておくことが大切です。その対策を何もしなければ、本来必要のなかったスケジュール調整に繋がってしまうと私は考えています。 もしスケジュール調整が発生してしまうと、上記マイルストーンに示したような状態になります。複数のテスト実施予定の変更だけではなく、急な要員調整が発生するなど困難な状況に陥りやすいです。 同じような悩みを持っている方に、少しでも参考になれば幸いです。 テスト開始に向けた対策 環境構築前の確認6W1H 環境構築ミスやヒューマンエラーといった事前対策には6W1Hという分析技法の活用が有効です。 6W1Hは、問題や課題を解決するために、いつ、だれが、何を、どこで、なぜ、どのように行うのかを明確にする技法です。具体的には、「When(いつ)」「Where(どこで)」「Who(誰が)」「Whom(誰に)」「What(何を)」「Why(なぜ)」「How(どのように)」の7つの質問を用いて詳細に分析します。そして、それぞれの答えをまとめることで、問題を解決するための具体的な計画を立てることができます。 この分析技法を用いて、使用するテストケースから必要な環境の洗い出しを行って、どのような環境がテストで必要かをまとめておきます。 私のやり方ですが、テスト環境構築の6W1Hを行い、その分析結果を基に環境構築の進め方を整理して、最後にはストーリーというものを作ることで理解しやすくしています。そうすることで、テスト環境に関わるステークホルダー全員と認識合わせを行う際にも「自分たちはこういうテストをするので、このような環境が必要です。」ということをはっきり示すことができます。また、環境を変更する必要性が発生してしまった際にもすばやい対応ができます。(ストーリーについては後述します。) ここからは6W1Hで分析するポイントを示します。問題となりやすいポイントを中心に分析することで、環境構築時に発生する問題が見えやすく、事前に解決することが可能になってきます。 <テスト環境構築の6W1H> ・When「いつテスト環境を構築するのか」 テスト環境を構築する日程を決めます。 ・Where「どこで端末を使用するのか」 どこで端末を使用するのかを決めます。他チームと共用で使用しているような場合はテスト期間中の端末を早めに抑えておきます。 ・Who「だれがテスト環境を構築するのか」 環境構築する担当者が決まっているか確認します。また、担当者レベルでは端末の過不足が把握しにくいことがあるため、環境構築する担当者任せにはしないことです。テスト環境を使用する担当者と環境構築する担当者との間で十分に認識を合わせるか、環境構築する担当者と一緒にやるつもりでいることが大切です。 ・Whom「だれにテスト環境を使ってもらうのか」 他チームも一緒に使用する可能性がある場合は他チームの要件も確認します。 ・What「なにを使用するのか」 テストで使用する環境の組み合わせが揃っているかや端末の初期状態を確認します。 <確認するポイントの例> ・テスト対象製品の詳細バージョン ・OSの詳細バージョン(パッチなど) ・その他に使用するツールやアプリケーションと詳細バージョン ・使用するドライバー等 ・製品・アプリ・ドライバ類の初期設定と状態 ・旧製品の有無(新旧で製品比較が必要な場合など) ・Why「なぜテストするのか」 テストが必要な理由を再確認します。テストする理由と構築するテスト環境に矛盾がないことを確認します。そして、認識齟齬をなくすために、テスト担当者と必要な理由について会話することが大切です。 ・How「どのようにテストするのか」 テストしやすい端末の配置を確認します。例えば、新旧製品の画面比較をするような場合には、新旧で横並びになっているかを確認します。もし向かい側に設置されてしまうと、それだけテストがやりにくくなり、進捗が大幅に悪くなってしまいます。 ストーリーとは 環境構築の6W1Hが終わった後はストーリーを作ります。ここでのストーリーとは、テスト環境に関して6W1Hの分析結果を整理したものです。ストーリーには、必ず目的やテーマがあり、環境構築の担当者とそのステークホルダー、出来事やエピソード、それらが起こる場所や時期などが含まれます。以下にその例を示しました。ストーリーは、プロジェクトごとにテンプレートを用意すると効率がよくなると思います。 <ストーリーの例> 目的 :システムテスト開始までに期待通りのテスト環境を構築する テーマ :期待通りのテスト環境が構築されていることを余裕をもって確認する 登場人物 :αチームの環境構築の担当者A、αチームのテスト担当者B、端末を共有で使用するβチームのテスト担当者C When :〇〇要件で、システムテストを〇月〇日から□月□日まで行うことが決まった。 Where :今度のシステムテストでは複数のシステムが連携しており、システムごとに拠点が異なっている。そのため、テストをどの拠点で行うかを確認した結果、拠点Aであった。 また、テスト端末は他チームとテスト期間が重なることが判明し、共有で使用することがわかった。 Who :システムテスト開始の三営業日前までにAさんが環境構築を行う計画を立てた。 その後、Bさんが端末の配置と要件通りにテスト環境が設定されているかをチェックする。 Whom :構築したテスト環境の端末をαチームとβチームで共有して使用するため、Cさんと打ち合わせを行い、必要な数の端末を揃えた。 What :テスト環境は、OSのバージョンはなんでもよく、Microsoft Edgeを推奨ブラウザとしてメインで使用している。 業務アプリは比較のために、新旧製品を用意した。また、テストでは印刷するため、プリンタドライバが必要であり、プリンタのデフォルト設定は顧客の指定通り、モノクロ・両面に設定した。 Why :テスト目的は移行性調査である。 移行性調査とは、非互換機能を正確に把握するために行うもので、特に操作性の観点で、旧製品と同じように動作していなければならない。 How :テストは旧製品と比較する観点があるため、旧製品と新製品を用意し、その端末を横並びになるように配置した。テスト終了後はAさんが端末を次のテストのために初期設定に戻すことになっている。 このようにストーリーを基に関係者間で十分に認識合わせを行うと、どのように環境構築を行うかが明確となり、設定ミスなどの環境構築ミスや、思い込みによるテスト端末間違いなどのヒューマンエラーを未然に防ぐことに繋がります。 上記に加え、以下にテスト実施前に確認してほしいポイントを示しました。参考になれば幸いです。 テスト設計者がテスト環境を確認する テスト環境はテスト実施する上で非常に重要です。テスト環境で失敗しないためには、テスト設計者が自らの目でテスト環境が正しく構築されていることやテスト条件が揃っているかを確認する必要があります。 これで認識齟齬などのヒューマンエラーは少なくなると思います。 問題が起きてしまったときの対策 ここからは万が一それでも問題が起きてしまったときの対策について、少しだけお話したいと思います。 前述のように考えられる対策をしても、テスト開始直後は、想定外の環境構築ミスがあったり、初めて触るモノだったり、仕様理解が不十分な場合、思い込み(ヒューマンエラー)でテストを行ってしまい、期待結果にならないことがあります。 もし、このようなミスが出てしまった場合には、その場ですぐに何か暗黙知(知らなかったこと)がなかったかをよく確認することと有識者を集めて認識合わせを行うことが大事だと思います。ミス発生直後の問題意識が高い状態で確認や認識合わせを行うことでミスの原因を効率的に特定して、取り除けると考えます。その結果、今後のスケジュール遅延予防に繋げることができます。 それでも問題が続いてしまうような場合には、「顕在化してしまった問題が解決するまでチーム内で助け合う体制を作る。」ということは効果があると考えます。チーム内で助け合う体制とは、例えば問題を抱えている人が何に困っているのかを自らが発信して、同じ問題を抱える人を集めたり、解決できそうな人に協力を求めて解決していくことを指します。 この体制を作る際に大事なことは当事者が問題をどのように捉え、それをどのように解決しようとしているかを明瞭にし、解決するための期間がどのくらい必要かを当事者自らが示すことです。当事者の「やりたいこと」が明瞭化されることによって、はじめて周囲から助けられる状態になります。 おわりに 今回のお話は以上になります。いかがだったでしょうか? 環境構築ミスやヒューマンエラーをなくすために大切なことをまとめると以下の3つです。 事前対策:6W1Hを行ってストーリーを作ることで認識合わせを行い、潜在問題を早期に解決する 事後対策:チーム内で助け合う体制を作ることで、迅速に問題を解決する。また、その後に同じような問題が発生することを防ぐ 中長期的な対策:問題解決に際して当事者の「やりたいこと」を明瞭にすることで、チームとしての問題解決力向上に繋げる 最後まで読んでいただきありがとうございました。 The post 環境構築ミスやヒューマンエラーをなくすためのノウハウ first appeared on Sqripts .
アバター
この連載は、登場して20年が過ぎ、成熟期を迎えつつある「アジャイル開発」を解説します。アジャイル開発については、世の中にたくさんの書籍や情報があふれていますが、アジャイルコーチとして10年以上の現場経験をもとに、あらためて学び直したい情報を中心にまとめていきます。 第3回目のテーマは、「従来型開発とアジャイル開発の違い」です。 この内容はUdemyで公開しているオンラインコース「 現役アジャイルコーチが教える!半日で理解できるアジャイル開発とスクラム 入門編 」の内容を元にしています。 なぜ比較をするのか? 従来型の代表的な開発手法としてウォーターフォール手法があります。従来型は予測しやすい開発に適用しやすい方法なので、予測型と呼ばれたりもします。一方、アジャイル型は変化に積極的に対応していきます。そのため、適応型と呼ばれたりもします。 この記事では従来型とアジャイル開発を様々な点で比較していきます。 比較することでそれぞれの違いがわかるようになり、選択肢が増えるはずです。選択肢が増えるので、自分の置かれた状況で何を選択すべきか意思決定しやすくなるでしょう。 また、それぞれの方法の理解が進むと、上手に使えるようになるのと同時に、今やっている方法がうまくいかない場合、何が原因なのかを特定しやすくなります。 それでは、従来型とアジャイル開発の比較を進めていきましょう。 プロセス全体の比較  プロセス全体の流れの比較図 まずはプロセス全体を比較してみましょう。上記の図は従来型とアジャイル開発のプロセス全体の流れを表現したものです。 上側は従来型です。図を見てのとおり、リリースまで一方通行で、滝のように流れていく工程のためウォーターフォール型と呼ばれます。 従来型では、それぞれの工程(フェーズ)を重視しています。工程をきちんと完了させ、うまくできてない場合は、次の工程に進めません。従来型でよく失敗してしまうのは、工程がうまくいっていないのに、期限があるから次の工程に進んでしまうケースです。ちゃんとやれば、従来型でもプロジェクトは成功するはずです。 従来型は最後の最後で完成品をリリースするため、最後に大きな利益を期待する方法です。うまくいけば大きな利益を得られますが、うまく行かない場合はやり直すにも時間がかかる方法なので大損害になります。 下側はアジャイル開発を表した図です。アジャイル開発は、短い開発サイクルを繰り返しながら進んでいきます。 短い開発サイクルのたびに、小さくリリースを繰り返しながら進んでいくため、リリースのたびに利益を小さく生み出せます。従来型のように大きな利益は期待できませんが、収益は小さくとも、従来型よりはやく利益を生み出せます。さらに、小さなリリースの繰り返しでプロダクトの改善がうまくすすめば、利益を増やしていくことができます。 アジャイル開発は、短い開発サイクルを繰り返すので、変化が起きたときに柔軟に対応できます。課題の改善も、次の開発サイクルから試せるため、すばやくやり直せます。 それぞれの方法の特徴を見ると、作りたいものがクリアに見えていたり、スケジュールがはっきりしていたり、物事を予測できる情報が多いなら従来型が進めやすいと思います。 一方で、見通せる情報が小さかったり、軌道修正に柔軟に対応しなければならないのであれば、アジャイル開発が進めやすいはずです。 プロジェクト運営の比較 次にプロジェクトの運営方法の比較をしてみましょう。従来型の特徴をいくつか見ていきましょう。 管理でコントロール プロマネが全体を管理(成熟した手法PMBOKもある) 工程ごと 従来型のプロジェクト運営は、どちらかというとかっちりした運営になります。これは、お客様と契約の関係があるケースが多いからでしょう。スコープ、スケジュール、コストが大切な変数になるプロジェクト型が多く、プロジェクトマネジメント手法を活用して、全体をきちんと管理していく必要があります。管理と言うとあまりいいイメージがわかないかもしれませんが、従来型では変化をできるだけ小さくしたいと考えています。 工程に分かれているのも特徴的です。工程ごとに担当する人や企業がわかれる場合も多いので、事前に決めた責務を、各自がやり遂げていく必要があります。だから、次の工程に進む場合、間違いがないようにバトンを渡す必要があるので、必然的にドキュメントが増えます。 一方で、アジャイル開発のプロジェクト運営はどうでしょうか? 自主性を重視 サーバント・リーダーシップ 開発サイクルごと アジャイル開発は、誰かが管理するのではなく、アジャイルチームメンバー全員で管理していこうとしています。アジャイル開発は、チームの自律性を重視します。アジャイルチームは、自分たちのゴールを常に意識し、それが達成できるかを日々確認しながら開発を進めます。 となると、アジャイル開発には、プロジェクトマネージャーは必要ないのかもしれません。そのかわりに登場するのがサーバント・リーダーシップです。サーヴァントとは、召使いという意味になり、サーバントリーダーシップが、自律したアジャイルチームを支える存在になります。 アジャイル開発は短い開発サイクルでわかれています。開発サイクル こうやって比較してみると、管理を行うのは誰か? が大きな違いとしてあります。リーダーシップの点も大きく異なり、従来型のリーダーシップと比べると、サーバントリーダーシップはだいぶ毛色の違う考え方になります。 組織・チームの比較 組織・チームを比較していきましょう。従来型の特徴以下です。 工程ごとの専任チーム 階層構造 プロジェクトや工程ごとにチームは解散 従来型は、先程も書きましたが、工程ごとに担当する人や企業がわかれる場合も多い方法です。ひとつの工程に複数企業が階層的に参加するケースも多いでしょう。 チームは、プロジェクトや工程の終わりに解散するケースもあります。 次に、アジャイル開発を見ていきます。 職能横断型チーム フラット メンバー固定 アジャイル開発では、職能横断型のチームを作ろうとします。職能横断型チームとは、やりたいことを実現できる人材の揃ったアジャイルチームです。もちろん、メンバーごとに専門性が異なったりするでしょうが、チームとしてゴールするという点が考えの中心にあることを忘れないでください。チームメンバーはフラットな関係性です。 アジャイル開発の場合、チームメンバーを固定します。固定して継続的に開発を繰り返していくので、チームの練度がどんどん高まっていきます。 従来型は、管理体制下で効率よく働ける組織・チームの構成になっています。アジャイル型は、チームを中心とした構成で、成果物の価値を高めていきます。 要求・要件・仕様・タスクの比較 要求・要件・仕様・タスクを比較していきましょう。従来型の特徴は以下です。 ドキュメント重視 WBS(Work Breakdown Structure:作業分解構成図) 従来型は、要求や要件などをドキュメントにしっかり落とし込んでいきます。契約のためでもありますし、工程に分かれているプロセスなので、工程が変わるときに間違いがおこらないようにドキュメントをしっかり残します。 従来型は、実現したいことが要求として管理され、要求は形を変えて仕様やタスクへと分割されていきます。従来型の場合、はじめから「作りたいもの」が見えているので(はじめに見つけるのは難しいですがそれは別の話)、WBSなどを活用し、作業分解して達成したい期日(リリース日)に当てはめていきます。 アジャイル開発の特徴は以下になります。 ユーザーストーリー 優先順位形式 アジャイル開発では、ユーザーストーリーという仕事の単位を好みます。ユーザーストーリーの例をあげるとすれば以下のようなシンプルな文章です。 顧客として、〜〜という結果を得るために、〜〜〜をしたい 仕事をユーザへの価値提供に直結させます。たりない情報をコミュニケーションや対話で埋めていこうとします。アジャイル開発では、従来型のしっかりしたドキュメントと異なり、あえて情報が足りない状態を作っているのです。 アジャイル開発でも計画は立てますが、アプローチの方法が従来型と異なります。アジャイル開発では、ユーザーストーリーを優先順位で並べるだけです。定期的にリリースを繰り返すので、優先順位の高いものから順番に開発され、できたものからどんどんリリースされます。 従来型とアジャイル開発では、仕事の単位がそれぞれ異なっています。アジャイル開発でもユーザーストーリーをタスクに分割しますが、大切なのはタスクよりも、ユーザーストーリー。すなわち、ユーザに提供する価値です。 今回は、4つの観点で比較をしました。 プロセス全体の比較  プロジェクト運営の比較 組織・チームの比較 要求・要件・仕様・タスクの比較 次回は見積もりと計画づくり、プロジェクト期間、品質などの比較を行っていきます。 第1回:アジャイル開発の過去、現在、未来を知ろう! 第2回:声に出して読みたいアジャイルマニフェスト The post 第3回 従来型開発とアジャイル開発の違い その1 first appeared on Sqripts .
アバター
こんにちは。 テストオートメーショングループのおすしです。 自動テストのテスト結果を確認していると、手動テストなら「問題なし」と判断できるエラーが出ていることはありませんか? テスト精度にブレがないのは非常に良い点なのですが、もう少し臨機応変にできないものか…と思ってしまいます。 例えば、アプリのデータ登録機能をテストする場合に、「登録した日時(yyyy/MM/DD hh:mm)が正しく表示されていること」という確認項目があるとします。 手動テストで確認する場合は、以下の流れで問題なく確認できます。 <手動テストの場合> アプリを操作してデータを登録する アプリ上のデータの登録日時が「2023/02/03 11:59」と表示されている PCの現在日時を見ると「2023/02/03 12:00(:01))」だった 2秒くらい前に登録操作をしたから、日時の表示は正しい! (※数秒のズレが許容されるテストの場合) ところが、自動テストの場合はそうはいきません。 <自動テストの場合> アプリを操作してデータを登録する アプリ上のデータの登録日時が「2023/02/03 11:59」と表示されている 現在日時を取得すると「2023/02/03 12:00」だった 一致しないので、日時の表示は間違っている! 日時の確認で安定して自動テストを動かすには、許容されるズレを含めた確認をする必要があります。 また、SaaSのテスト自動化ツールの多くは海外サーバー上で動作しています。そのため、自動テストで現在日時を取得すると、アプリで使用しているタイムゾーンと異なる日時を取得してしまう場合があります。 指定したタイムゾーンの現在日時を取得する必要があります。 今回はこの2つの課題をJavaScriptで解決したお話です。 以下の順番で解説していきます。 【課題1】テスト実行環境のローカルタイムがテスト対象のタイムゾーンと異なる 【課題2】1秒でもずれるとテストが失敗してしまう 実装シナリオ ボタンを押した日時が記録されるWebアプリを例にして説明します。 テスト対象の画面仕様 ・トレーニングを3個選択し、「実行しました!」ボタンをクリックするとその時刻が「最終実行日時」に登録される ・日時の表示は「yyyy/mm/dd hh:mm:ss」 テスト内容 操作: 1.トレーニングリストの「チェック」欄を3箇所ONにする 2.「実行しました!」のボタンをクリックする 確認内容: チェックを入れたデータの「最終実行日時」が、ボタンをクリックした日時と一致していること レコード時の問題点 可変の現在日時を確認する機能がないため、既存機能だけではテストが実装できません。 JavaScriptのコード 【課題1】テスト実行環境のローカルタイムがテスト対象のタイムゾーンと異なる まずは手元のパソコンで現在日時を取得してみます。 ブラウザの開発ツールからコンソールウィンドウを開いて以下のJavaScriptコマンドを実行します。 Date(); <結果> Thu Feb 16 2023 14:41:57 GMT+0900 (日本標準時) 同じコマンドを、SaaSの自動化ツール上で実行してみます。 <結果> Thu Feb 16 2023 05:36:54 GMT+0000 (Coordinated Universal Time) テスト自動化ツールの実行サーバーは世界標準時のようです。 Date()はローカルタイムを取得するため、実行したマシンの影響を受けます。 テスト対象の「筋トレアプリ」は常に日本標準時で日時を記録する仕様です。 そのため、テスト時も日本標準時の時間を取得する必要があります。 自動テストツールの実行環境が常に世界標準時とは限らないため、取得したローカルタイムを世界標準時に合わせた後、日本標準時に調整することにします。 /** * 現在の日本標準時刻を返します。 * ローカルタイムにかかわらず常に日本標準時を返します。 * @returns{string} 日時 */ function getJapanStandardTime() { //現在日時を取得(1970 年 1 月 1 日 00:00:00 から経過したミリ秒数の形式) const localDateAndTime_ms = Date.now(); //ローカルタイムと世界標準時の差を取得(ミリ秒数に合わせる) const localTimezoneOffset_ms = new Date().getTimezoneOffset() * 60 * 1000; //日本標準時のオフセットを計算(ミリ秒数に合わせる) const JAPAN_TIMEZONE = 9; const JAPAN_TIMESONE_OFFSET_ms = JAPAN_TIMEZONE * 60 * 60 * 1000; //世界標準時との差をなくしてから日本標準時にする const utcDateTime = localDateAndTime_ms + localTimezoneOffset_ms; const japanDateTime = utcDateTime + JAPAN_TIMESONE_OFFSET_ms; return japanDatesAndTimes; } 【課題2】1秒でもずれるとテストが失敗してしまう 秒数までの日時を確認する場合、アプリのデータ登録と現在日時の取得が1秒でもずれると一致しないのでテストが失敗します。 そこで、テスト時にずれても許容範囲内の日時を準備します。 引数「offset_sec」に渡した秒数が許容範囲になります。 /** * 現在の日本標準時刻と、指定した秒数を±した時刻の3つを配列で返します。 * ローカルタイムにかかわらず常に日本標準時を返します。 * @param {number} offset_sec 許容範囲内とする秒数のズレ(秒) * @returns{arry} 現在時刻-offset_sec、現在時刻、現在時刻+offset_secの配列 */ function getJapanStandardTime(offset_sec) { //現在日時を取得(1970 年 1 月 1 日 00:00:00 から経過したミリ秒数の形式) const localDateAndTime_ms = Date.now(); //ローカルタイムと世界標準時の差を取得(ミリ秒数に合わせる) const localTimezoneOffset_ms = new Date().getTimezoneOffset() * 60 * 1000; //日本標準時のオフセットを計算(ミリ秒数に合わせる) const JAPAN_TIMEZONE = 9; const JAPAN_TIMESONE_OFFSET_ms = JAPAN_TIMEZONE * 60 * 60 * 1000; const offset_ms = offset_sec * 1000; //世界標準時との差をなくしてから日本標準時にする const utcDateTime = localDateAndTime_ms + localTimezoneOffset_ms; const japanDateTime = utcDateTime + JAPAN_TIMESONE_OFFSET_ms; const japanDatesAndTimes = []; japanDatesAndTimes.push(new Date(japanDateTime - offset_ms)); japanDatesAndTimes.push(new Date(japanDateTime )); japanDatesAndTimes.push(new Date(japanDateTime + offset_ms)); return japanDatesAndTimes; } <5を渡した場合の結果> 現在日時マイナス5秒、現在日時、現在日時プラス5秒の3つの日時が算出されます。 (3) [Thu Feb 16 2023 18:09:29 GMT+0900 (日本標準時), Thu Feb 16 2023 18:09:34 GMT+0900 (日本標準時), Thu Feb 16 2023 18:09:24 GMT+0900 (日本標準時)] 0:Thu Feb 16 2023 18:09:24 GMT+0900 (日本標準時) {} 1:Thu Feb 16 2023 18:09:29 GMT+0900 (日本標準時) {} 2:Thu Feb 16 2023 18:09:34 GMT+0900 (日本標準時) {} 次に、渡した日時が許容範囲内かを判定する処理を作成します。 Date.parse()は日付形式のテキストを渡すと、1970 年 1 月 1 日 00:00:00 から経過したミリ秒数の形式に変換してくれるメソッドです。 先程作成した「getJapanStandardTime」を中に入れています。 /** * 引数で渡した日時が、現在日時の±指定秒数以内であるかを判定します。 * @param date {string} "yyyy/mm/dd hh:mm:ss"形式の日時 * @param offset_sec {number} 許容範囲内とする時間のズレ(秒) * @author osushi */ function checkDateAndTimeAcceptable(date, offset_sec) { //引数チェック if (!offset_sec) { throw new Error("2番目の引数が入力されていません"); } else if (typeof(offset_sec) !== "number"){ throw new Error("offset_secは数値を入力してください") } //テストで使用する日時を取得 const dates = getJapanStandardTime(offset_sec); //テスト対象の日時、比較対象の日時をミリ秒表記にする const dateAndTimeMinus = Date.parse(dates[0]); const dateAndTimeNow = Date.parse(date); const dateAndTimePlus = Date.parse(dates[2]); if (dateAndTimeMinus < dateAndTimeNow && dateAndTimeNow < dateAndTimePlus) { console.log("日時データは許容範囲内です"); } else { console.log("dateAndTimeMinus : ",dateAndTimeMinus); console.log("dateAndTimeNow : ",dateAndTimeNow); console.log("dateAndTimePlus : ",dateAndTimePlus); throw new Error("日時データが許容範囲内ではありません"); } /** * 現在の日本標準時刻と、指定した秒数を±した時刻の3つを配列で返します。 * ローカルタイムにかかわらず常に日本標準時を返します。 * @param {number} offset_sec 許容範囲内とする秒数のズレ(秒) * @returns{arry} 現在時刻-offset_sec、現在時刻、現在時刻+offset_secの配列 */ function getJapanStandardTime(offset_sec) { //現在日時を取得(1970 年 1 月 1 日 00:00:00 から経過したミリ秒数の形式) const localDateAndTime_ms = Date.now(); //ローカルタイムと世界標準時の差を取得(ミリ秒数に合わせる) const localTimezoneOffset_ms = new Date().getTimezoneOffset() * 60 * 1000; //日本標準時のオフセットを計算(ミリ秒数に合わせる) const JAPAN_TIMEZONE = 9; const JAPAN_TIMESONE_OFFSET_ms = JAPAN_TIMEZONE * 60 * 60 * 1000; const offset_ms = offset_sec * 1000; //世界標準時との差をなくしてから日本標準時にする const utcDateTime = localDateAndTime_ms + localTimezoneOffset_ms; const japanDateTime = utcDateTime + JAPAN_TIMESONE_OFFSET_ms; const japanDatesAndTimes = []; japanDatesAndTimes.push(new Date(japanDateTime - offset_ms)); japanDatesAndTimes.push(new Date(japanDateTime )); japanDatesAndTimes.push(new Date(japanDateTime + offset_ms)); return japanDatesAndTimes; } } テスト実装 あとは「最終実行日時」のテキストを取得し、作成した関数に渡すだけです。 <テストの流れ> トレーニングリストの「チェック」欄を3箇所ONにする 「実行しました!」のボタンをクリックする ページから「最終実行日時」を取得する※1 「checkDateAndTimeAcceptable」に手順3のテキストと許容範囲とする秒数を渡して確認する ※1 ページ内の特定のテキストを取得するJavaScriptスニペットは、Autifyの公式ページで紹介されています。 Autify JavaScript Snippets おわりに 今回は以下の課題と解決案を解説しました。 【課題1】コードを実行したローカル環境の現在日時を取得してしまう → 解決策:オフセットを利用して現在日時を取得したいタイムゾーンに調整する 【課題2】1秒でもずれるとテストが失敗してしまう →  解決策:ズレの許容範囲を指定して、その範囲内かを判定する 将来、優秀なテスターのようにテストを実行してくれるAIが開発されたら、自動的に許容範囲かを判断してテストできるようになるかもしれません。 テストはすべてAIにおまかせして、実装にかける工数を増やせるようになるといいですね。 The post テスト自動化ツールで使えるJavaScriptテクニック紹介「日時を確認する」 first appeared on Sqripts .
アバター
前回のおさらい 前回の記事 では、E2Eテストの自動化において最初に気をつけるべき目的の設定と毎日テストを実行することの重要性、そして導入のステップについてお伝えしました。第2回となる今回は、実際に毎日の自動テストの運用を始めてから遭遇しがちな具体的な課題と対策についてお話ししたいと思います。 運用時にありがちな課題 自動テストの運用で、必ずと言っていいほど出てくるのが以下のような課題です。 失敗したテストの解析に時間がかかる 自動テストは実行したら当然結果を確認し、失敗したテストがあればアプリケーションの不具合によるものなのか、テストケースに誤りがあるのか、または環境要因かを切り分けてそれぞれ対処する必要があります。毎日の作業なので、ここに時間がかかり過ぎると「自動テスト=つらいもの」という認識が生まれ、自動テストをさらに有効活用していこうというモチベーションが失われてしまいます。 Flakyなテスト(結果が一定にならず、成功したり失敗したりするテスト)がある 実行の内容やどのようなアサーション(結果の確認)を入れているかにもよりますが、「同じ手順で実行しているはずなのになぜか時々失敗してしまうテスト」というのは非常によく発生します。前述の「失敗したテストの解析」をひときわ難しくするのがこのFlakyなテストです。原因はテスト対象のアプリケーションのレスポンスタイムのちょっとしたずれ、ブラウザのバージョンアップなど様々で、筆者が経験した中では「テスト用のPCでウィルスチェックが走って動作が重くなったため」というものもありました。 実行時間が長い E2EテストはUnitテストに比べてどうしても実行時間が長くなりがちです。そのため前回記事の冒頭でも「テストのピラミッド」として紹介したようにそもそも数を多く作りすぎないことも重要なのですが、必要なテストだけでも数時間となってしまうこともあります。すると前日の開発分のテストが翌日朝に終わらないという状況になり、フィードバックが遅れることで自動テストへの対応が遅くなる→メンテナンスしづらくなり陳腐化するというリスクがあります。 これらの問題をすべて解決する銀の弾丸は存在しませんが、意識しておくべきかどうかで大きく結果が変わってくるのが「テストケースの独立性」というキーワードです。 独立性とは? 「良い単体テストの条件」として有名な「F.I.R.S.Tの原則」というものがあります。それぞれFast(迅速)、Isolated/Independent(独立)、Repeatable(繰り返し可能)、Self-validating(自己検証可能)、Timely(タイムリー)の頭文字を取っています。単体テストとE2Eテストでは前提条件が大きく異なりますが、E2EテストでもIndependent(独立)とRepeatable(繰り返し可能)の原則はとても重要です。テストが独立していて繰り返し可能であるということは、つまり日次実行のときと同じ順序で実行する必要がなく1ケースだけで実行可能であり、何度実行しても同じ結果になるということです。 これが達成されていると、以下のようなメリットがあります。 失敗したときに素早く単独で再実行できる:テストケースが独立していると、失敗したテストだけを再実行することが容易になります。これにより、毎日の解析と修正が迅速に行えるようになります。 Flakinessにも対応しやすい:上と同じ理由で手軽に再実行できるためどれくらいFlakyであるかを簡単にチェックできるというメリットが1つあります。加えて、そもそもテストが繰り返し実行可能でないこと自体がFlakinessを生んでいる場合も多い(前回のテストで生成されたデータを正しく削除していないと次回のテストが失敗する等)ため、対処すべきFlakinessが減るというメリットもあります。 実行時間を短くできる:独立性が保たれているテストケースは、(多くの場合)並列実行が可能になります。その結果、テスト全体の実行時間が短縮され、開発者に素早いフィードバックを提供できます。 いかがでしょうか。ありがちな課題に応えられているように見えますね。 具体的に独立性を保つための工夫 では、テストケースの独立性を保つための具体的な工夫を紹介していきましょう。必要に応じて、AIを利用した自動テストサービス「MagicPod」を使ってどのように設定ができるかも一緒に見ていきます。 開始時の状態に依存しない 「独立性を保つ」とほとんど意味は同じなのですが、ここではテスト対象のアプリケーションを操作する上で開始時にどういう状態になっているか、というような意味でとらえていただければと思います。代表的なものとしては、「ログインしている」「ログインしていない」のような状態の違いが考えられますね。もしくは、「最初に必要なチュートリアルを終えている」「終えていない」といったものもあります。 たとえばテストケースの最初に「ログイン画面でIDとパスワードを入力してログインする」といったステップを入れてしまうと、アプリケーションの仕様にもよりますが実行開始時にすでにログイン済みだった場合は違う画面に遷移してしまって失敗することが多いでしょう。状態に依存しないテストにするためには、「(ログイン後でないと開けない)マイページに遷移する。もしログイン画面が表示されたら、IDとパスワードを入力してログインする」といったように条件分岐を使えばOKです。 実際に両者のテストケースを作成してみるとこんな風になります。 データ・アカウントを分ける これは特に全体を並列実行したいときに重要な項目です。複数のテストケースで必要なデータを共有してしまうと、1つのケースを変更したときに他のケースが動かなくなってしまい非常にメンテナンスしづらくなります。表示確認するだけのようなケースならそれほど問題ありませんが、大抵のテストではデータに何らかの変更を加えてその結果を確認すると思いますのでケース毎に分離させるのは重要です。また、テスト対象のシステムにもよりますが多くのシステムではアカウント(ユーザ)毎に異なるデータを持ちますのでアカウントから分けてしまうのも手です。あまり分けすぎると認証情報などの管理が大変になるので、筆者のチームでは アカウントの特性によらない一般的な操作のテスト→汎用のテスト用アカウント 外部ID連携、エンタープライズユーザなどアカウントの特性に合わせたテスト→ケース毎の専用アカウント といった分け方で運用しています。 使用するデータは極力テストケース内で作る 前の項目と似ていますが、さらに繰り返し可能性を高めるために「ケース1ではデータAを使う」というような分離ではなく「ケース1を実行するときは毎回必要なデータを生成する」という仕組みにしておくと便利です。こうしておけば、実行時に何らかの不具合でデータがおかしくなったとしても次回実行ではクリーンな状態で始めることができます。 「毎回データを作る」というとそれだけで実行時間が長くなってしまいそうな気がしますが、テスト対象のシステムにデータを登録できるAPIがあれば素早くデータを準備できます。MagicPodには「Web APIコール」というコマンドがあり、ブラウザの操作とは別に任意のAPIを実行することができます。この機能を使うことで、画面操作だけでは実現が難しかったり時間がかかりすぎたりする操作も簡潔に行えます。 変数の活用 データの話が続きましたが、色々と工夫を重ねても毎回全く同じ結果にはできないようなものもあります。日付が絡む処理や、ニュースのように日々変わる内容の表示などです。こういった固定できない内容を使ったテストでは、変数を活用しましょう。 たとえば、ホテルの予約ページのテストをする際に毎回未来の日付を入力しなければいけないとします。下図のように日付を格納する変数(ここでは「DATE」という名前)を用意し、常に2日後の日付を入れるようにすればテストを実行するたびに適切な日付を入力できます。 また、ニュースの見出しが記事の一覧画面と詳細画面で一致していることを確認するなら、一覧画面で見出しの内容を変数「TITLE」に保存しておき、詳細画面の見出しと比較することができます。 テスト環境の日付やニュースの内容もテスト環境の構築方法によっては頑張って固定化できなくもないですが、あまりに固執しすぎると特定のデータで起きる不具合を見逃す可能性もあります。変数を使って緩やかにテストできる部分では積極的に使ってみましょう。 毎回同じ環境で実行する こちらは少し毛色が変わって、「独立」よりも「繰り返し可能」に重点をおいたポイントです。E2Eの自動テストはとにかくちょっとした外部要因で結果が変わりやすいので、外部要因の差を排除したクリーンな環境で実行することが大切です。 最近はクラウド環境で指定のブラウザ・デバイスでテストできるサービスも沢山あります。実行環境の整備はそれだけでかなりの手間がかかりますので、テストの内容に集中するためにも環境を安定させるのはそういったサービスに任せてしまったほうが良いでしょう。 毎回同じ環境でテストを実行しているとスクリーンショットも基本的にまったく同じになるので、下のように期待値の画像とピクセル単位で比較することも可能です。 こちらは上の2つの画像から差分だけを抽出したものです。レイアウトに変更があった箇所だけがハイライトされ、OKかどうかの確認がしやすくなっています。 まとめ 今回は、自動テストの運用を無理なく続けるために意識すべきテストの独立性についてお伝えしました。「独立」というキーワードを意識することで、実行時間の長さ・解析時間の長さ・Flakyなテストによる苦痛などをある程度解決することができます。テストツールによって解決できる課題もありますが、どんなデータを使ってどのようにテストケース間の依存を防ぐかという設計の部分はツールによらず工夫が必要なのでテストエンジニアの腕の見せどころです。 次回は、さらに短い時間で自動テストの恩恵を受けるためのテストケース作成時の工夫をお伝えします。 第1回:E2Eテストの自動化を最速で成功させる秘訣 The post 第2回:毎日の自動テストを無理なく続けるためのキーワード first appeared on Sqripts .
アバター
お久しぶりです。インフラソリューション部の“のなか”です。 今回は 前回 に続き、AWS上で稼働している既存WordPressを更新する際にかかっているデプロイ時間を30分から5分に圧縮した話をしていきます。 前編ではWordPressを構築しましたが、後編では自動デプロイを設定していきます。 それではWordPressのデプロイ自動化の後編を始めていきましょう! 注意点 – 前編 で説明した内容は省略 前提条件 – 前編 を実施済み – SSHの公開鍵と秘密鍵を作成済み – WSL2にzipパッケージをインストール済み 用語説明 EC2 Image Builderとは 後編に入る前にEC2 Image Builderについて説明します。 EC2 Image Builderとは公式ドキュメントのユーザーガイドで以下のように説明されています。 EC2 Image Builder is a fully managed AWS service that helps you to automate the creation, management, and deployment of customized, secure, and up-to-date server images. You can use the AWS Management Console, AWS Command Line Interface, or APIs to create custom images in your AWS account.  説明を1行でまとめるとイメージの作成、管理、デプロイを自動化するツールです。例えば 公式ドキュメント では以下の図で説明されています。 以下の順番で実行し、この一連の処理を イメージパイプライン と言います。 1. イメージからインスタンスを起動 2. (ビルド)元のイメージにソフトウェアをインストール 3. インスタンスを終了 4. ソフトウェアをインストールイメージからインスタンスを起動 5. (テスト)作成したイメージをテスト 6. インスタンスを終了 7. テストしたイメージから ゴールデンイメージ を作成 イメージのビルドとテストが可能になるため、イメージの管理やセキュリティの担保がマネージドサービスから行えますが、2回インスタンスの起動と終了が行われるため、実行時間が30分程度かかります。 ※実行時間はイメージ毎で異なります。 ドキュメントルート配下をデプロイするだけであれば、CodeDeployのみでも良いですが、EC2自体を更新したい場合は試してみると良いと思います。 後編のリソース作成手順 手順 1. TerraformでCodeCommitを作成 2. TerraformでDeployを作成 3. TerraformでCodePipelineを作成し、動作確認 4. TerraformでEC2 Image Builderを作成 5. TerraformでLambdaを作成 6. TerraformでCodePipelineにLambdaを追加し、動作確認 後編のシステム図と使用するAWSのリソース システム図 使用するAWSのリソース – CodeCommit – CodeDeploy – CodePipeline – S3 – Lambda – EC2ImageBuilder 後編のディレクトリ構成 Terraform 後編の ~/terraform-blog は以下のディレクトリ構成になります。 . ├── .terraform │ └── providers │ └── registry.terraform.io │ └── hashicorp │ └── aws │ └── 4.57.1 │ └── linux_amd64 │ └── terraform-provider-aws_v4.57.1_x5 ├── .terraform.lock.hcl ├── README.md ├── aws_asg.tf ├── aws_codepipeline.tf ├── aws_data.tf ├── aws_ec2.tf ├── aws_iam.tf ├── aws_imagebuilder.tf ├── aws_s3.tf ├── aws_vpc.tf ├── lambda_function.py ├── lambda_function.py.zip ├── provider.tf ├── terraform.tfstate └── terraform.tfstate.backup 構築 IAMを設定 1. AWSのコンソールにサインインし、Basic_Groupユーザーグループに以下ポリシーをアタッチ – AmazonS3FullAccess – AutoScalingFullAccess – AWSCodeCommitFullAccess – AWSCodeDeployFullAccess – AWSCodePipeline_FullAccess – AWSImageBuilderFullAccess – AWSLambda_FullAccess 1. vi ~/terraform-blog/aws_iam.tf でROLE_BLOGロールのポリシーを追加 #---------------------------------------- # IAMロールを作成 #---------------------------------------- resource "aws_iam_role" "ROLE_BLOG" { name = "ROLE_BLOG" assume_role_policy = "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}" description = "Allows EC2 instances to call AWS services on your behalf." path = "/" managed_policy_arns = [ "arn:aws:iam::aws:policy/AmazonEC2FullAccess", "arn:aws:iam::aws:policy/AmazonSSMFullAccess", # 追加 "arn:aws:iam::aws:policy/AmazonS3FullAccess", "arn:aws:iam::aws:policy/AWSCodePipeline_FullAccess", "arn:aws:iam::aws:policy/AWSImageBuilderFullAccess" ] tags = { Name = "ROLE_BLOG" } } CodeCommitを設定 まずはドキュメントルートを自動デプロイするため以下システムを構築していきます。 ※①~④の説明は 前編 を確認して下さい。 1. BlogUserのセキュリティ認証情報画面で、AWS CodeCommitのSSH公開キーに作成済みのSSH公開鍵をアップロードして、SSHキーIDをメモ 1. WSL2で vi ~/terraform-blog/aws_codepipeline.tf を実行し、CodeCommitの設定を追記 resource "aws_codecommit_repository" "BlogCodecommitRepo" { repository_name = "BlogCodecommitRepo" tags = { Name = "BlogCodecommitRepo" } } 1. Terraformを実行し、CodeCommitにリポジトリを作成 terraform planterraform apply 1. CMSサーバー(EC2)とCMSサーバー(ASG)にSSHし、AWS CodeCommitのSSH公開キーに登録した公開鍵をauthorized_keysに追記し、秘密鍵を配置 以下は秘密鍵がid_rsaの場合のディレクトリ例です。 [root@ip-10-0-0-10 .ssh]# ls -al合計 8drwx------ 2 root root 43 5月 16 10:26 .dr-xr-x--- 6 root root 185 5月 16 10:25 ..-rw------- 1 root root 553 5月 16 09:45 authorized_keys-rw------- 1 root root 1675 5月 16 10:25 id_rsa 1. vi ~/.ssh/config でSSHの設定ファイルを作成 以下は秘密鍵がid_rsaの場合の設定ファイルです。 Host git-codecommit.*.amazonaws.com User (1でメモしたSSHキーIDをここに入力) IdentityFile ~/.ssh/id_rsa 1. chmod 600 ~/.ssh/config でSSHの設定ファイルの権限を変更 drwx------ 2 root root 76 5月 12 10:35 .dr-xr-x--- 6 root root 203 5月 12 10:35 ..-rw------- 1 root root 553 5月 8 10:19 authorized_keys-rw------- 1 root root 89 5月 8 10:58 config-rw------- 1 root root 1675 5月 2 09:56 id_rsa-rw-r--r-- 1 root root 1230 5月 8 13:53 known_hosts 1. CMSサーバー(EC2)にSSHし、 vi /var/www/html/appspec.yml で自動デプロイするための設定ファイルを作成 version: 0.0os: linuxfiles: - source: / destination: /var/www/htmlfile_exists_behavior: OVERWRITE 1. CodeCommitのリポジトリにドキュメントルート配下をpush cd /var/www/html/yum install -y gitgit init .git add .git commit -m "first push"git push --set-upstream ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/BlogCodecommitRepo master ※以降は以下のコマンドでCodeCommitにpushします。 cd /var/www/html/git add .git commit -m "change config"git push CodeDeployを設定 1. WSL2で vi ~/terraform-blog/aws_codepipeline.tf を実行し、CodeDeployの設定を追記 #---------------------------------------- # CodeDeployのアプリケーションを作成 #---------------------------------------- resource "aws_codedeploy_app" "BlogCodedeployApp" { name = "BlogCodedeployApp" compute_platform = "Server" tags = { Name = "BlogCodedeployApp" } } #---------------------------------------- # CodeDeployのデプロイグループを作成 #---------------------------------------- resource "aws_codedeploy_deployment_group" "BlogCodedeployDeployGroup" { app_name = aws_codedeploy_app.BlogCodedeployApp.name deployment_group_name = "BlogCodedeployDeployGroup" service_role_arn = aws_iam_role.CodeDeployServiceRole.arn deployment_config_name = "CodeDeployDefault.AllAtOnce" autoscaling_groups = [aws_autoscaling_group.BlogASG.name] auto_rollback_configuration { enabled = true events = ["DEPLOYMENT_FAILURE"] } deployment_style { deployment_option = "WITHOUT_TRAFFIC_CONTROL" deployment_type = "IN_PLACE" } tags = { Name = "BlogCodedeployDeployGroup" } } 1. vi ~/terraform-blog/aws_iam.tf でCodeDeployのサービスロールの設定を追記 #---------------------------------------- # IAMロールを作成 #---------------------------------------- resource "aws_iam_role" "CodeDeployServiceRole" { name = "CodeDeployServiceRole" assume_role_policy = "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"codedeploy.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}" description = "Allows CodeDeploy to call AWS services such as Auto Scaling on your behalf." path = "/" managed_policy_arns = [ "arn:aws:iam::aws:policy/AWSCodeDeployFullAccess", "arn:aws:iam::aws:policy/AmazonEC2FullAccess" ] tags = { Name = "CodeDeployServiceRole" } } 1. Terraformを実行し、CodeDeployを作成 terraform planterraform apply 1. CMSサーバー(EC2)とCMSサーバー(ASG)にSSHし、CodeDeployのエージェントをインストール sudo su -yum -y install ruby wget gitwget -P /tmp https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/installchmod +x /tmp/install/tmp/install auto 1. CMSサーバー(ASG)にSSHし、WordPressのドキュメントルートをクローン cd /var/www/html/rm -rf /var/www/html/*git clone ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/BlogCodecommitRepo . CodePipelineを設定 1. vi ~/terraform-blog/aws_s3.tf を実行し、データを格納するためのS3のバケットを作成 resource "aws_s3_bucket" "blogbucketwp" { bucket = "blogbucketwp" tags = { Name = "blogbucketwp" } } resource "aws_s3_bucket_server_side_encryption_configuration" "blogasbssec" { bucket = aws_s3_bucket.blogbucketwp.bucket rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } bucket_key_enabled = true } } resource "aws_s3_bucket_request_payment_configuration" "blogbucketwpasbrpc" { bucket = aws_s3_bucket.blogbucketwp.bucket payer = "BucketOwner" } 1. WSL2で vi ~/terraform-blog/aws_codepipeline.tf を実行し、CodePipelineの設定を追記 #---------------------------------------- # CodeCommitのリポジトリを作成 #---------------------------------------- resource "aws_codecommit_repository" "BlogCodecommitRepo" { repository_name = "BlogCodecommitRepo" tags = { Name = "BlogCodecommitRepo" } } #---------------------------------------- # CodeDeployのアプリケーションを作成 #---------------------------------------- resource "aws_codedeploy_app" "BlogCodedeployApp" { name = "BlogCodedeployApp" compute_platform = "Server" tags = { Name = "BlogCodedeployApp" } } #---------------------------------------- # CodeDeployのデプロイグループを作成 #---------------------------------------- resource "aws_codedeploy_deployment_group" "BlogCodedeployDeployGroup" { app_name = aws_codedeploy_app.BlogCodedeployApp.name deployment_group_name = "BlogCodedeployDeployGroup" service_role_arn = aws_iam_role.CodeDeployServiceRole.arn deployment_config_name = "CodeDeployDefault.AllAtOnce" autoscaling_groups = [aws_autoscaling_group.BlogASG.name] auto_rollback_configuration { enabled = true events = ["DEPLOYMENT_FAILURE"] } deployment_style { deployment_option = "WITHOUT_TRAFFIC_CONTROL" deployment_type = "IN_PLACE" } tags = { Name = "BlogCodedeployDeployGroup" } } #---------------------------------------- # CodePipelineを作成 #---------------------------------------- resource "aws_codepipeline" "BlogCodepipelinePipeline" { name = "BlogCodepipelinePipeline" role_arn = aws_iam_role.ServiceRoleCodePipeline.arn stage { name = "Source" action { name = "Source" namespace = "SourceVariables" category = "Source" owner = "AWS" provider = "CodeCommit" version = "1" region = "ap-northeast-1" output_artifacts = ["SourceArtifact"] configuration = { BranchName = "master" OutputArtifactFormat = "CODE_ZIP" PollForSourceChanges = "true" RepositoryName = aws_codecommit_repository.BlogCodecommitRepo.repository_name } } } stage { name = "Deploy" action { name = "Deploy" namespace = "DeployVariables" category = "Deploy" owner = "AWS" provider = "CodeDeploy" version = "1" region = "ap-northeast-1" input_artifacts = ["SourceArtifact"] configuration = { ApplicationName = aws_codedeploy_app.BlogCodedeployApp.name DeploymentGroupName = aws_codedeploy_deployment_group.BlogCodedeployDeployGroup.deployment_group_name } } } artifact_store { location = aws_s3_bucket.blogbucketwp.bucket type = "S3" } tags = { Name = "BlogCodepipelinePipeline" } } 1. vi ~/terraform-blog/aws_iam.tf でCodePipelineのサービスロールの設定を追記 #---------------------------------------- # IAMロールを作成 #----------------------------------------] resource "aws_iam_role" "ServiceRoleCodePipeline" { name = "ServiceRoleCodePipeline" assume_role_policy = "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"codepipeline.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}" description = "" path = "/service-role/" managed_policy_arns = [ "arn:aws:iam::aws:policy/AWSCodePipeline_FullAccess", "arn:aws:iam::aws:policy/AWSCodeCommitFullAccess", "arn:aws:iam::aws:policy/AWSCodeDeployFullAccess", "arn:aws:iam::aws:policy/AWSLambda_FullAccess", "arn:aws:iam::aws:policy/AmazonS3FullAccess", "arn:aws:iam::aws:policy/AWSImageBuilderFullAccess", "arn:aws:iam::aws:policy/AmazonEC2FullAccess" ] tags = { Name = "ServiceRoleCodePipeline" } } 1. Terraformを実行し、CodePipelineを作成 terraform planterraform apply 1. CodePipelineのSourceとDeployが成功することを確認 自動デプロイの動作確認 1. CMSサーバー(EC2)にSSHし、権限を変更 sudo chmod 777 -R /var/www/html/wp-content/* 1. CMSサーバー(EC2)の管理画面のテーマエディターで背景色を修正 以下はデフォルトのテーマTwenty Twenty-Oneのstyle.cssのbodyの背景色を白色に修正した例です。 1. CMSサーバー(ASG)にブラウザからアクセスし、背景色がデフォルトであることを確認 1. CMSサーバー(EC2)にSSHし、ドキュメントルート配下をCodeCommitにpush sudo su -cd /var/www/htmlgit add .git commit -m "change config"git push 1. CMSサーバー(ASG)にブラウザからアクセスし、背景色を修正されていることを確認 ※CodePipelineが処理中であれば反映されていないことがあるため、5分程度おいて再度確認してください。 EC2 Image Builderを設定 1. WSL2で vi ~/terraform-blog/aws_data.tf を実行し、アカウント情報を取得する設定を追記 data "aws_caller_identity" "current" {} 1. vi ~/terraform-blog/aws_imagebuilder.tf を実行し、EC2 Image Builderの設定を追記 #---------------------------------------- # EC2 Image Builderのビルド用コンポーネントを作成 #---------------------------------------- resource "aws_imagebuilder_component" "BlogBuildComponent" { name = "BlogBuildComponent" platform = "Linux" supported_os_versions = ["Amazon Linux 2"] version = "1.0.0" data = "name: HelloWorldTestingDocument\ndescription: This is hello world testing document.\nschemaVersion: 1.0\n\nphases:\n - name: build\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Build.\"\n\n - name: validate\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Validate.\"\n\n - name: test\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Test.\"\n" tags = { Name = "BlogBuildComponent" } } #---------------------------------------- # EC2 Image Builderのテスト用コンポーネントを作成 #---------------------------------------- resource "aws_imagebuilder_component" "BlogTestComponent" { name = "BlogTestComponent" platform = "Linux" supported_os_versions = ["Amazon Linux 2"] version = "1.0.0" data = "name: HelloWorldTestingDocument\ndescription: This is hello world testing document.\nschemaVersion: 1.0\n\nphases:\n - name: test\n steps:\n - name: HelloWorldStep\n action: ExecuteBash\n inputs:\n commands:\n - echo \"Hello World! Test.\"\n" tags = { Name = "BlogTestComponent" } } #---------------------------------------- # EC2 Image Builderのイメージレシピを作成 #---------------------------------------- resource "aws_imagebuilder_image_recipe" "BlogImageRecipe" { name = "BlogImageRecipe" parent_image = aws_ami_from_instance.BlogAMI.id version = "1.0.0" working_directory = "/tmp" block_device_mapping { device_name = "/dev/xvda" ebs { delete_on_termination = true encrypted = false volume_size = 8 volume_type = "gp2" } } systems_manager_agent { uninstall_after_build = false } component { component_arn = aws_imagebuilder_component.BlogBuildComponent.arn } component { component_arn = aws_imagebuilder_component.BlogTestComponent.arn } tags = { Name = "BlogImageRecipe" } } #---------------------------------------- # EC2 Image Builderのイメージレシピを作成 #---------------------------------------- resource "aws_imagebuilder_infrastructure_configuration" "BlogInfra" { name = "BlogInfra" instance_profile_name = aws_iam_role.ROLE_BLOG.name instance_types = ["t2.micro"] key_pair = "KEY_BlogSample" security_group_ids = [aws_security_group.sg_blog.id] subnet_id = aws_subnet.pub_subnet1a_blog.id terminate_instance_on_failure = true tags = { Name = "BlogInfra" } } #---------------------------------------- # EC2 Image Builderのディストリビューションを作成 #---------------------------------------- resource "aws_imagebuilder_distribution_configuration" "BlogDist" { name = "BlogDist" distribution { region = "ap-northeast-1" ami_distribution_configuration { name = "BlogAMI{{imagebuilder:buildDate}}" ami_tags = { Name = "BlogImageBuilderAMI" } } launch_template_configuration { account_id = data.aws_caller_identity.current.id default = true launch_template_id = aws_launch_template.BlogTemplate.id } } tags = { Name = "BlogDist" } } #---------------------------------------- # EC2 Image Builderのイメージパイプラインを作成 #---------------------------------------- resource "aws_imagebuilder_image_pipeline" "BlogImagePipeline" { name = "BlogImagePipeline" status = "ENABLED" distribution_configuration_arn = aws_imagebuilder_distribution_configuration.BlogDist.arn enhanced_image_metadata_enabled = true image_recipe_arn = aws_imagebuilder_image_recipe.BlogImageRecipe.arn infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.BlogInfra.arn image_tests_configuration { image_tests_enabled = true timeout_minutes = 720 } tags = { Name = "BlogImagePipeline" } } 1. Terraformを実行し、イメージパイプラインを作成 terraform planterraform apply 1. イメージパイプラインを実行し、動作確認 以下のようにエラーが出力されていないことを確認します。 CodePipelineでEC2 Image Builderを呼び出す 1. WSL2で vi ~/terraform-blog/lambda_function.py を実行し、EC2 Image Builderを呼び出すLambdaのソースコードを作成 import boto3 import logging import json import os import traceback logger = logging.getLogger() logger.setLevel(logging.INFO) codepipeline_client = boto3.client('codepipeline') imagebuilder_client = boto3.client('imagebuilder') # AMI作成の成功時の処理 def put_job_success(job_id): logger.info('Putting job success') codepipeline_client.put_job_success_result(jobId=job_id) # AMI作成中の時の処理 def continue_job_later(job_id,image_build_version_arn): logger.info('Putting job continuation') continuation_token = json.dumps({'ImageBuildVersionArn':image_build_version_arn}) codepipeline_client.put_job_success_result( jobId=job_id, continuationToken=continuation_token ) # AMI作成の失敗時の処理 def put_job_failure(job_id, err): logger.error('Putting job failed') message = str(err) codepipeline_client.put_job_failure_result( jobId=job_id, failureDetails={ 'type': 'JobFailed', 'message': message } ) # codepipelineからlambda_functionを呼び出し def lambda_handler(event, context): try: job_id = event['CodePipeline.job']['id'] job_data = event['CodePipeline.job']['data'] image_pipeline_arn = os.environ['IMAGE_PIPELINE_ARN'] pipeline_name = os.environ['CODEPIPELINE_NAME'] logger.info('ImagePipelineArn is %s', image_pipeline_arn) logger.info('CodePipeline Event is %s',event['CodePipeline.job']) # 継続トークンの有無を確認 if 'continuationToken' in job_data: continuation_token = json.loads(job_data['continuationToken']) image_build_version_arn = continuation_token['ImageBuildVersionArn'] logger.info('ImageBuilderVersionArn is %s', image_build_version_arn) # ビルドの状態を取得 response = imagebuilder_client.get_image( imageBuildVersionArn = image_build_version_arn ) build_status = response['image']['state']['status'] logger.info('ImageBuild Status is %s',build_status) # 処理の結果が成功なら状態をAVAILABLEに遷移 if build_status == 'AVAILABLE': put_job_success(job_id) # 処理の結果が失敗なら状態をFAILEDに遷移 elif build_status == 'FAILED': errmsg='Build Error' put_job_failure(job_id, errmsg) # 処理が継続中の場合continue_job_later関数を呼び出す else: continue_job_later(job_id,image_build_version_arn) else: # ビルドを実行 response = imagebuilder_client.start_image_pipeline_execution( imagePipelineArn=image_pipeline_arn ) image_build_version_arn = response['imageBuildVersionArn'] logger.info('imageBuildVersionArn is %s', image_build_version_arn) continue_job_later(job_id,image_build_version_arn) # 例外処理 except Exception as err: logger.error('Function exception: %s', err) traceback.print_exc() put_job_failure(job_id, 'Function exception: ' + str(err)) logger.info('Function complete') return "Complete." 1. Lambdaのソースコードをzip形式で圧縮 cd ~/terraform-blog/sudo zip lambda_function.py.zip lambda_function.py 1. vi ~/terraform-blog/aws_s3.tf を実行し、Lambdaのソースコードを保持するS3の設定を追記 resource "aws_s3_object" "lambdacode" { bucket = aws_s3_bucket.blogbucketwp.bucket key = "lambda_function.py.zip" source = "~/terraform-blog/lambda_function.py.zip" etag = filemd5("~/terraform-blog/lambda_function.py.zip") } 1. Terraformを実行し、Lambdaのソースコードを保持するS3を作成 terraform planterraform apply 1. vi ~/terraform-blog/aws_codepipeline.tf を実行し、Lambdaリソースを作成する設定とLambdaを呼び出す設定を追記するためファイルを書き換える #---------------------------------------- # CodeCommitのリポジトリを作成 #---------------------------------------- resource "aws_codecommit_repository" "BlogCodecommitRepo" { repository_name = "BlogCodecommitRepo" tags = { Name = "BlogCodecommitRepo" } } #---------------------------------------- # CodeDeployのアプリケーションを作成 #---------------------------------------- resource "aws_codedeploy_app" "BlogCodedeployApp" { name = "BlogCodedeployApp" compute_platform = "Server" tags = { Name = "BlogCodedeployApp" } } #---------------------------------------- # CodeDeployのデプロイグループを作成 #---------------------------------------- resource "aws_codedeploy_deployment_group" "BlogCodedeployDeployGroup" { app_name = aws_codedeploy_app.BlogCodedeployApp.name deployment_group_name = "BlogCodedeployDeployGroup" service_role_arn = aws_iam_role.CodeDeployServiceRole.arn deployment_config_name = "CodeDeployDefault.AllAtOnce" autoscaling_groups = [aws_autoscaling_group.BlogASG.name] auto_rollback_configuration { enabled = true events = ["DEPLOYMENT_FAILURE"] } deployment_style { deployment_option = "WITHOUT_TRAFFIC_CONTROL" deployment_type = "IN_PLACE" } tags = { Name = "BlogCodedeployDeployGroup" } } #---------------------------------------- # Lambdaを作成 #---------------------------------------- resource "aws_lambda_function" "BlogImageBuilderFunction" { architectures = ["x86_64"] s3_bucket = aws_s3_bucket.blogbucketwp.bucket s3_key = "lambda_function.py.zip" function_name = "BlogImageBuilderFunction" handler = "lambda_function.lambda_handler" memory_size = 128 package_type = "Zip" reserved_concurrent_executions = -1 role = aws_iam_role.ServiceRoleLambda.arn runtime = "python3.9" timeout = 3 tracing_config { mode = "PassThrough" } ephemeral_storage { size = 512 } environment { variables = { CODEPIPELINE_NAME = "BlogCodepipelinePipeline" IMAGE_PIPELINE_ARN = aws_imagebuilder_image_pipeline.BlogImagePipeline.arn } } tags = { Name = "BlogImageBuilderFunction" } } #---------------------------------------- # CodePipelineを作成 #---------------------------------------- resource "aws_codepipeline" "BlogCodepipelinePipeline" { name = "BlogCodepipelinePipeline" role_arn = aws_iam_role.ServiceRoleCodePipeline.arn stage { name = "Source" action { name = "Source" namespace = "SourceVariables" category = "Source" owner = "AWS" provider = "CodeCommit" version = "1" region = "ap-northeast-1" output_artifacts = ["SourceArtifact"] configuration = { BranchName = "master" OutputArtifactFormat = "CODE_ZIP" PollForSourceChanges = "true" RepositoryName = aws_codecommit_repository.BlogCodecommitRepo.repository_name } } } stage { name = "Deploy" action { name = "Deploy" namespace = "DeployVariables" category = "Deploy" owner = "AWS" provider = "CodeDeploy" version = "1" region = "ap-northeast-1" input_artifacts = ["SourceArtifact"] configuration = { ApplicationName = aws_codedeploy_app.BlogCodedeployApp.name DeploymentGroupName = aws_codedeploy_deployment_group.BlogCodedeployDeployGroup.deployment_group_name } } } stage { name = "Invoke" action { name = aws_lambda_function.BlogImageBuilderFunction.function_name namespace = "InvokeVariables" category = "Invoke" owner = "AWS" provider = "Lambda" version = "1" region = "ap-northeast-1" input_artifacts = [] output_artifacts = [] configuration = { FunctionName = aws_lambda_function.BlogImageBuilderFunction.function_name } } } artifact_store { location = aws_s3_bucket.blogbucketwp.bucket type = "S3" } tags = { Name = "BlogCodepipelinePipeline" } } 1. Terraformを実行し、CodePipelineを作成 terraform planterraform apply 1. 作成したCodePipelineを実行し、動作確認 動作確認 1. CMSサーバー(EC2)の管理画面のテーマエディターで背景色を修正 以下はデフォルトのテーマTwenty Twenty-Oneの style.css のbodyの背景色を黒色に修正した例です。 1. CMSサーバー(ASG)にブラウザからアクセスし、背景色が白色であることを確認 1. CMSサーバー(EC2)にSSHし、ドキュメントルート配下をCodeCommitにpush sudo su -cd /var/www/htmlgit add .git commit -m "change config"git push 1. CMSサーバー(ASG)にブラウザからアクセスし、背景色を修正されていることを確認 ※CodePipelineが処理中であれば反映されていないことがあるため、30分程度おいて再度確認してください。 改善点 今回は権限を非常に緩く設定しましたが、実際に使用する際は適宜読み替えて権限を設定してください。 バージョン管理もgitを使ったことがない人でも使えるようにコマンドを固定していますが、コンフリクトが発生する等のリスクがあるため、gitを使える人はブランチを切ったりコミットメッセージを変更する等適宜読み替えてください。 また、イメージの管理にEC2 Image Builderを使用しましたが、ゴールデンイメージ作成に30分程度かかるため、ビルドとテストを行う必要が無ければ AWS Backup を使用する等の別の方法を使用した方が良いです。 IAMをTerraformで resource で管理していますが、 data source を使用した方がスクラップ&ビルドしやすいです。 所感 今回はイメージの管理を自動化しましたが、EC2からAMIを取得する作業や、AMIが正常に取得しているかの確認をする作業がマネージドサービスで自動化できるため非常に便利でした。 前編 と合わせて、ドキュメントルート配下の自動デプロイ、AMI管理の自動化、Ansibleによるプロビジョニングの自動化、Terraformによるインフラのコード化等の様々なツールを紹介しましたが、全てのツールを使用しなくても何か一つでも試すと作業が快適になると思います。 前編と後編を合わせるとかなりボリュームがありますが、ここまで読んで頂きありがとうございました。 The post 【後編】WordPressをIaCで管理して自動デプロイを実現!! first appeared on Sqripts .
アバター
テスト設計をする際には、テスト技法を使うことで、効率的に効果的なテストケースを作ることができます。今回、本稿で紹介する技法となる「順序組み合わせテスト」と「波及全使用法:IDAU法」は、バージョンアップ開発や派生開発などで、テスト対象に変更が入ったときに役立つテスト技法です。これまでの7回の連載では、前半の4回はこの技法の特徴や具体的な使い方を湯本から紹介し、連載の後半では、後続研究として取り組んだCode Based IDAU法(CB-IDAU)とグラフ特徴量バグ予測モデル(GMT)を武田から紹介しました。 連載の最終回である今回はすこし話を変えて、この技法を今後どうしていくとよいのかを武田と湯本の対談でお伝えしたいと思います。 スクリプター: 武田 友宏(たけだ ともひろ)のプロフィールはこちら これまでの7回の連載を終えて 湯本: 武田さん、今回はIDAU法の連載に協力してもらってありがとうございました。連載を通じて、私も改めて武田さんの研究成果を見直す機会になったので、とてもよかったです。武田さんはどうでしたか? 武田: 論文で書いたことを要約しつつ、わかりやすく読者の方々に伝える機会ができて、自分の頭の中を整理できたのでとてもよかったです。ありがとうございました。 湯本: 今後の展開について話すのが今日のテーマなのですが(笑)。私は、IDAU法はバージョンアップ開発や派生開発などで、テスト対象に変更が入ったときに役立つテスト技法として研究しましたが、一番の想いは、現場で多くの人に適用してもらいたいことであるため、ツール化して汎用的に使えるようにできないかなって思っているんです。武田さんが後続研究でテーマにしたCB-IDAUなんかは、ツール化して汎用的に使ってもらうのがやりやすいんじゃないかなって思っています。武田さんはどう思いますか? 武田: 実は、私がCB-IDAUについて研究していたころと事情が異なってきていると思っています。最近ではChatGPTのようにすでにプログラムやコーディングパターンを大規模言語モデルとして学習済みのAI技術が出てきたので、CB-IDAUのようなテストは、うまくプロンプトを書けばできるのではないか?と思うようになりました。プログラムを学習済みの大規模言語モデルを使うことで、そもそも誰でもコードがプロンプトを使って簡単に作れるようになりました。なので、テストコードも同様に作れます。コードがあり、そこに対して一定のルールベースでテストを導き出すだけのことであれば、もはやAIのほうが確実に作れます。わざわざ人間がやるような時代ではなくなるのではないかと思います。 セマンティックなテストは人間が行なわなければならない 武田: ただし、システムテストで行うリグレッションテストをAIに学習させて良いテストが作れるようにするのは今後も可能性を感じます。セマンティック(データの持つ意味をコンピュータに理解させ処理する技術)なテストには人間が入れる余地が十分にあると思います。湯本さんとしては、IDAU法を今後どのように広げていきたいのですか? 湯本: IDAU法に基づいたテストケースのパターンが導き出せるツールが作れると良いと思っています。状態遷移モデルを描くとスイッチカバレッジのパターンを出してくれるようなツールがあるのですが、そのIDAU法バージョンのようなものです。 武田: それは、ソフトウェア設計者が作成したDFDをベースにするようなイメージですか? 湯本: 私のイメージは、システムテストをテスト設計する際にモデリングするようなイメージです。そして、単なるDFDではなく、CRUDの情報も付加できるように拡張したモデルにして、テストに必要なCRUDのパターンが導き出せるようにしたいです。 ソースコードからリバースして確認する 武田: Code Based IDAU法(CB-IDAU)がソースコードからIDAU法の考え方に基づくテストパターンを生成する方法ですので、ソースコードからリバースしたパターンと湯本さんが話している方法で生成したパターンを比較して確認するのはどうでしょうか?そこで差異があれば、それはバグなのではないかと考えられます。 湯本: なるほど、いいところに目をつけていますね!それは、実はデシジョンテーブルで同様の先行研究があります。筑波大学大学院の研究室で私や武田さんの先輩にあたる植月さんの研究がまさにそれで、” An Efficient Software Testing Method by Decision Table Verification ”という論文にて、研究成果を発表しています。 武田: コードからのリバースはどのような方法で実現しているのですか? 湯本: コンコリックテスティングです。 武田: なるほど。全パス解析をして、そこからデシジョンテーブルを作るのですね。 湯本: そうです。何か良い説明資料はないかな?(グーグルで検索をする)あー、植月さんがJaSST(ソフトウェアテストシンポジウム)で講演している資料で「 はじめてのコンコリックテスト 」というのがありますね。研究の内容も要約して説明されています。 武田: ありがとうございます。また後でしっかり読んでみます。このような話を自分で切り出しておきながらあえて言うのですが、課題が二つあると思いました。一つは、仕様から導いたパターンと、コードからリバースしたパターンでは途中経過で多くの設計行為が入り、単純に同じにならないので、比較が難しいと思うということです。もう一つは、コードからリバースしたらパターン数が爆発するので、絞り込みルールが必要になるということです。 湯本: まず、パターンの爆発に関しては、それを防ぐために最初に機能セット(feature set)を特定するようにしています。IDAU法は、データアクセスに対する順序性でパターンを作るので、変更が入ったタスク群、つまり先行の立脚点になるタスクが含まれている機能セットを選んで、その後に波及するタスク群、つまり後続の選択肢となるフィーチャーが洗い出されるので、選ばれるコードも絞り込まれます。絞り込まれることによって、爆発は防げるはずです。また、比較が難しい件に関しては、デシジョンテーブルで行った先行研究でも全く同じ課題はあるので、先行研究の中に解決の鍵があると思っています。 武田: コードからリバースする場合なのですが、選ばれるコードを絞り込む際に、入力のデータセットとエンティティとの関係を洗い出さないといけないと思います。コードレベルになると、現実的にデータセットがそのまま一つのエンティティに入るわけではなく、一部はここ、もう一部はここというようなロジックが複雑に入るので、入力のデータセットとエンティティの関係に対する解析が必要です。 湯本: 確かに。画面から入力した情報がデータベースに書き込まれるときに、画面とエンティティが1対1のような関係になることは稀ですね。マイクロサービスアーキテクチャーのような構造だとさらに複雑な関係になることも十分考えられます。最初から全部いっぺんに解決できる方法を頭の中だけで考えていくのは大変だから、ステップ切って少しずつ試していかないと解決策見いだせなさそうですね。 武田: データの遷移(1カラムのデータに対する処理の順番)に絞ってスモールスタートでプロトタイプ検証していきたいです。 湯本: ぜひやりたいですね。データのCRUDレベルで変更が入ったときの影響範囲は、確実にテストできるようにしていきたいです。このレベルのバグは重篤度(Severity)がCriticalになるものが多くいからです。 まとめ 今回は、順序組み合わせテストとIDAU法というテスト技法について説明をする連載の最終回目として、武田と湯本でIDAU法の未来を話し合う対談をさせてもらいました。この後は、「このようなツールを作るとしたら、資金調達しないといけない」という話になり、世の中では、このようなことを実現したい時にはどうやって資金調達するのかといったビジネス的な話で盛り上がりました。 以上で連載は終わりになりますが、今回の対談にあるような研究を継続し、またどこかで成果を発表できるようにしていきたいと思っていますので、そのときをぜひ楽しみにしてください。 The post 【第8回】変更の影響範囲に対するテスト技法の今後の展開 first appeared on Sqripts .
アバター
こんにちは。QAエンジニアをしている有名じゃない方の高橋です。 お客様先で品質支援やテストマネージャーをしています。 5/26に開催された、JaSST’23Tohokuにオンライン参加してきました。 テーマに「アジャイルとテストと私たち~明日「アジャイル」と言われたときに困らないためのヒント~」とあるとおり、アジャイルをテーマにしたセッションが並びます。 今回は、S1)基調講演 「アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発」 についてレポートしたいと思います。 JaSSTとは JaSSTとは「ソフトウェアテストおよびソフトウェア品質に関心のある方が深い学びを得ることを目指して、 ソフトウェアテスト分野の幅広い情報と、参加者同士の交流や議論ができる場を提供」するため、特定非営利活動法人ソフトウェアテスト技術振興協会 (ASTER)が主催する日本最大級のソフトウェアテストのシンポジウムになります。 公式ページ JaSST’23Tohoku公式ページ S1)基調講演「アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発」 基調講演をされた川口恭伸さんは「ユーザーストーリーマッピング」監訳を始め、スクラム関連の書籍を複数、共訳、監修しているお方です。 今回のセッションでは、ユーザーストーリーマッピングは何を求められて生まれ、何が出来るかの説明から入り、ユーザーストーリーマッピングの作成方法についてお話されていました。 要点をまとめつつ、セッションを通して感じたこと、学んだことを記していこうと思います。 ユーザーストーリーマッピングとは ユーザーストーリーマッピングを提唱するジェフ・パットンさんや、UXでは知らない人がいないペルソナを生み出したアラン・クーパーさんの話からなぜユーザーストーリーマッピングが必要なのか説明していました。 ユーザーストーリーマッピングは、プログラマとデザイナーの間で認識齟齬をなくすため、共通認識を作り上げるためために必要です。 両者が協調ワークショップを通じて共通体験をすることで情報の力(共有知)を得ることが出来ます。 一緒に作り上げることが重要であると再三言われていました。 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf P17 バケーションフォト 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p19 壁を使用して付箋を使い作成していきます。 付箋を使用するときに気を付けてること すべての情報を記載しない 付箋にすべては書ききれない 共通認識を思い出すためのトリガーとして使う 作成したバケーションフォトは壁にそのまま貼っておくとよいそうです。画像に残して片づけてはいけないとのことです。 なぜならプロジェクト中に何度も見に戻って来て、そのたびに作成時に会話した共通理解を思い出すことが出来るからだそうです。 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p22 ユーザーストーリーマッピング作成の流れ 1.必要なことを書き出す 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p41 2.並べる 以降は※基調講演の内容から作成したイメージ図 3.ラベルを付ける 4.ラベルに大項目を付ける 5.リリースまでに必要なラインを決める 6.POが優先度をつけて減らす 7.ファーストリリースから外す 8.価値が提供できるか検証する (ウォークスルー) ペルソナを使用して検証 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p42 POやスポンサーがリリースのために優先度を付けているところ 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p43 まとめ アジャイル開発においてどのようにQAするか、どこまでテストするかなどのお話はほとんどありませんでした。 ただユーザーストーリーマッピングの本質を理解することで要求から品質を作りこむことが出来ると感じました。 テスト量によるリスク検知 機能数が多くなるにつれてシステムテスト工数が増大する セキュリティや性能テストのタイミング どの機能まで出来れいれば対象機能のテストが可能か 自動化対象の対象選定 開発順を考慮してリグレッションテストの価値が最大化できるように選定する また一番心に響いた話が、「製品開発の目標は、製品を作ることではない。」です。 出典: J 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p62 私達はどうしてもアウトプット部分に拘ってしまいがちです。 どの機能を追加した 全体的な品質は担保出来た 仕様を整理した資料を書き残した しかし、それは結果コンテキストから見ると関係ありません。 製品がユーザーに届き利用してもらった、結果(成果)と、価値(インパクト)の最大化が製品開発の目標です。そのため結果コンテキストが同じであればアウトプットはなるべく小さい方がよいと教えて頂きました。 自分の中で言語化出来ていない部分だったので、今回お話を聞きながら赤べこの様に頷いていました。 おまけ JIRA(タスク管理)で有名なATLASSIAN開発チームも壁と付箋でユーザーストーリーマッピングを整理していた事があるそうです。 出典: 20230526JaSST-Tohoku_アジャイルテスター視点で、ユーザーストーリーマッピングを活用した効果的なプロダクト開発.pdf p50 The post ユーザーストーリーマッピング作成で大事な事とQAのポイント~JaSST’23Tohoku参加レポート first appeared on Sqripts .
アバター
みなさん、こんにちは! QA事業本部のゆーすけです。 連載形式でJSTQB FLの解説をしており、第6回連載ではテスト技法の途中まで書かせていただきました。 今回テスト技法の続き、、と見せかけて、2023年4月にISTQB FLシラバスのメジャーバージョンが4.0にあがったので、こちらについてちょっと触れていきたいと思います。 ISTQB CTFL Syllabus v4.0 Certified Tester Foundation Level (CTFL) v4.0 [NEW!] こちらはまだJSTQBによる日本語訳は出ていないので、現在はISTQBの英語版のみの提供となります。 Version2018時のリリース時系列を見る限りは、ISTQB→JSTQBリリースまで半年程度になっていますので、2023年の下期にはJSTQBからリリースされるのではないかと思います。 そしてJSTQB FL資格への適用は21年2月(当時はPBT)からとなっていますので、現在行っているFL CBT試験の内容の3.1→4.0適用は1年近く先のことになるかもしれません。 とはいえ、学習してほしい内容の指針が変更→ベースとして求められる知識幅の変更になっているので、直近でFL資格取得を考えている人、既にFLを取得している人含め、全てのISTQB/JSTQB学習者は是非把握しておくべき内容だとは思います。 以下、有識者の見解および機械翻訳をベースで大きな変更点について触れていきたいと思います。 Testing Throughout the Software Development Lifecycle 2.1に ・Testing as a Driver for Software Development ・DevOps ・shift-left ・Retrospectives などの項目が追加されています。 DevOps、シフトレフト、レトロスペクティブなどはすっかり耳なじみとなったワードですよね。 Testing as a Driver for Software Developmentはテストのことを考えた開発体制であり、シラバスでは ・TDD(テスト駆除開発) ・ATDD(受け入れテスト駆除開発) ・BDD(ビヘイビア駆除開発) が挙げられており、こちらもよく聞くワードになっていると思います。 ATDDはTest Analysis and Design(テスト技法)の項目にも取り上げられていますので、理解し活用できるようにしておきましょう。 Static Testing 静的テストの項目は、一部レビュー観点のものが削除されたようです。 Test Analysis and Design まずは、ユースケーステストの項目が削除されました! つい最近、 JSTQB学習のススメ #6 〜Foundation〜 | Sqripts こちらでユースケーステストのことを書いたばかりなので、残念という思いもありますが、FLでユースケーステストの内容をこの粒度で記載するのもどうなんだろう、という思いもあったので、納得と言えば納得だったりします。 あとは、中項目として「Collaboration-based Test Approaches」が追加されており、内容としては、 ・Collaborative User Story Writing ・Acceptance Criteria. ・Acceptance Test-driven Development (ATDD). の3章構成となっています。 ・Collaborative User Story Writing 日本語で馴染みの言葉にすると「ユーザーストーリーマッピング」になるのかな、と思います。 これに関しては直近(5/26)開催されたJaSST東北で、ユーザーストーリーマッピングに関する基調講演が行われており、そちらに関する参加記事が載る(載っている?)予定ですので、そちらを見ていただければと思います。 Acceptance Criteriaは「受け入れ基準」という日本語訳になり、ATDDはそのままの用語で日本でも使われていると思いますが、日本語訳だと「受け入れテスト駆除開発」になります。 TDD、レトロスペクティブなど含め、全体的にアジャイルの要素が入っているのがCTFL 4.0のイメージですね。 Managing the Test Activities テスト技法からユースケーステストが削除されたように、FLのテストマネジメントからは 「テスト戦略とテストアプローチ」が削除になったようです。 またテストマネジメントの項目も他同様、アジャイルや自動化の概念から ・Test Pyramid(テストピラミッド) ・Testing Quadrants(テストの四象限) の項目が追加されています。 Test Tools FLのレベルの適切ではない項目が何点か削除されているようです。 おそらくテスト自動化含め、AL側に移行されるものかと考えられます。 まとめ 全ての変更点を網羅しているわけではないですが、ざっと気になったところをまとめるとこのようなかたちになると思います。 気になる方は原文を訳しながら読んでみることをおススメします。 また、シフトレフト、CD/CI、TDDなどは、AGESTでは「QA for Development」 というソリューション提案をしておりますので、気になった方はこちらも確認いただけると幸いです。 「QA for Development」ソリューション – 株式会社AGEST(アジェスト) では、次回こそはFLシラバスのテスト技法の続きを載せたいと思います。 JSTQBのFLシラバス4.0がリリースされる前には、3.1ベースのものは全て書ききりたい、と思っていますので、引き続きお付き合いいただければと思います! The post 【最新動向】ソフトウェアテストの国際規格「ISTQB CTFL」4.0の爆速レビュー first appeared on Sqripts .
アバター
こんにちは、テストオペレーショングループのりきおです。 本記事は、スプレッドシートで作成したテスト項目書に対してGAS(GoogleAppsScript)を使って体裁修正する方法についてご紹介していきたいと思います。テスト項目書はもちろん、あらゆるドキュメント作成の際に少しでもご参考にして頂けると幸いです。 ※なお、本記事では「デザイン」「見た目」等は、まとめて「体裁」と総称します。 はじめに いきなりですが、下図のように同一の項目内容で体裁のみが異なるテスト項目書があったとします。 それぞれを見比べたとき、どちらがより 見やすい と感じますか? あるいは、どちらがより 円滑にテストを実行できそう だと感じますか? パターンA パターンB ・ ・ ・ 恐らく、多くの人は パターンB を選ぶのではないでしょうか。 パターンBは、項目の所属がカテゴライズ化されたような体裁となっているため、「どの画面(大項目)」の「どの場所(中項目)」の「どの機能(小項目)」を指しているのかが、パターンAよりも識別しやすくなっています。上図の例では項目数が20個と少ないため、両者の視認レベルにそこまで大きな差異はありませんが、例えば、項目数が数百~数千項目に及んでいたり、項目内で似たような文言が散見されるような場合だと、より顕著な結果となるのではないでしょうか。 しかし、上記で挙げたように数百~数千項目が記載されたテスト項目書を手動で体裁修正した場合、それなりに作業工数がかかってしまったり、また、コピペで修正した場合には修正対象や記載内容の誤植といったヒューマンエラーが起きる可能性があることも事実です。 そのような事態を踏まえて、今回はパターンBを例にスプレッドシートで作成したテスト項目書に対してGASを使って一発で体裁修正したときの方法について、次章以降より解説していきたいと思います! 要件定義 それでは、コーディングに入る前にパターンBがどのように体裁修正されているかを一度整理しておきましょう。 1.基本要件 はじめに、体裁修正を行う要件を確認していきます。修正内容をまとめると、以下の通りとなっていることが分かります。 ・同列の上下で同じ値が連続する場合、下のセルの文字色をグレーに変更する ・同列で上下で同じ値が連続する場合、下のセル上部の罫線を非表示とする ・「中項目」は「大項目+中項目」、「小項目」は「大項目+中項目+小項目」でそれぞれ比較する 2.機能要件 続いて、上節で整理した内容に基づき、機能要件を手順に沿って定義していきましょう。 基本機能(判定・描画処理) 1. 制御処理:実行回数(N回目)を確認し、状態に応じて以下の通り制御する  1-A:指定した回数に到達した場合     ・体裁修正処理を終了する  1-B:指定した回数に未達の場合     ・「2. 判定処理」以降の処理を行う 2. 判定処理:各列の項目間の上下行(N行とN+1行)の値を比較する  ※上下行の値が「同じ」と判定される条件は以下の通り  ・大項目:「大項目」の上下行の値が同じ  ・中項目:「大項目」「中項目」の上下行の各値がそれぞれ同じ  ・小項目:「大項目」「中項目」「小項目」の上下行の各値がそれぞれ同じ 3. 修正処理:「2. 判定処理」の比較結果に応じて以下の通り体裁修正する  3-A:同じ値だった場合、下行(N+1行)の項目を以下に体裁修正する     ・文字色設定:グレー(#cccccc)     ・上罫線描画:FALSE  3-B:異なる値だった場合、下行(N+1行)の項目を以下に体裁修正する     ・文字色設定:そのまま(何もしない)     ・上罫線描画:TRUE 4. 実行回数や比較対象の行数にて共通で使用しているインデックス(N)をインクリメントし、「1. 制御処理」に戻る フローチャート: 実際のコーディング処理とは少し異なりますが、イメージとしては下図のような感じとなります。 補足: ・初回実行時、上行(項番#1)の項目は修正対象とならないため、以降の処理でも常に「下行(N+1行)」の項目を修正対象とします。 ・「3-B:異なる値だった場合」の処理として、パターンAのように体裁修正前の全ての項目が「文字色:黒」かつ「横罫線:あり」となっていれば「何もしない処理」でも問題ないですが、テスターへの注記として意図的に文字色が黒以外に設定されていたり、罫線が描画されていないといった体裁上の誤植があった場合などを考慮して、今回は「文字色:そのまま」「上罫線描画:TRUE」とします。 以上が今回の要件の概要となります。 本章でまとめた要件を元に、次章でコーディングしていきましょう! コーディング 本記事ではGASのエディタページのコーディングから解説していきます。 ※GASの概要については、別記事「 業務改善にはコレ!\Google Apps Script/ 」でもご紹介しております。ご興味がある方、GASとはなんぞやという方は、是非読んでみて下さい。 1.スプレッドシート・項目シートの取得 はじめに、実行対象となるスプレッドシートと項目シートを取得しましょう。 関数名は「TestSheetFix」としています。 function TestSheetFix() { const activeSheet = SpreadsheetApp.getActiveSpreadsheet(); const activeSheetName = SpreadsheetApp.getActiveSheet().getName(); const fixSheet = activeSheet.getSheetByName(activeSheetName); 今回はアクティブ状態のシート(現在開いているシート)であれば全てのシートが実行対象となるようにコーディングしているため、シート名に依存せずに実行することができます(間接参照)。 言い換えれば、実行対象以外のシートがアクティブだった場合にも体裁修正処理が走るので、扱いには少し注意が必要です。 補足 実行対象のシート数が少ない場合や特定のシートに対して実行したいといった限定的な用途であれば、以下のように実行対象のシート名を直値で指定する方法でも良さそうです(直接参照)。 function TestSheetFix() { const activeSheet = SpreadsheetApp.getActiveSpreadsheet(); const fixSheet = activeSheet.getSheetByName('実行対象のシート名'); 2.行・列・範囲の取得 次に、取得したシート内で実行対象となる行・列・実行範囲を定義していきましょう。 対象は以下4点です。 1)先頭行の定義 はじめに、実行範囲や修正対象となる行を指定するために、上図スプレッドシートで赤枠に該当する行位置の変数を定義しておきます。 let firstRowUpper = 4; let firstRowLower = firstRowUpper + 1; ・firstRowUpper(先頭上行):4行目 ・firstRowLower(先頭下行):5行目(先頭上行+1行) 2)最終行の定義 続いて、体裁修正する範囲の末尾を決定するために、上図スプレッドシートで赤枠に該当する行位置の変数を定義しておきます。 let lastRow = 23; ・lastRow(最終行):23行目 3)実行範囲の定義 項目の先頭行と最終行を取得した後は、それぞれを減算して体裁修正する実行範囲(実行回数)を定義しましょう。 let fixRange = lastRow - firstRowUpper; ・fixRange(19) :lastRow(23) – firstRowUpper(4)  ※「下行」が修正対象であり一番最後に実行する行は22行目(最終行 – 1行目)のため、全項目数に対して1項目少ない値が実行範囲となります。 4)列番号の定義 最後に、比較対象や実行する列を指定するために、上図スプレッドシートで赤枠に該当する列番号を定義しておきます。 let primaryItemCol = 3; let secondaryItemCol = primaryItemCol + 1; let tertiaryItemCol = primaryItemCol + 2; ・primaryItemCol(大項目列)  :C列=3列目 ・secondaryItemCol(中項目列):D列=4列目(大項目列+1列目) ・tertiaryItemCol(小項目列)   :E列=5列目(大項目列+2列目) 変数の戻り値 デバッグで各変数の戻り値を確認してみると、下図の結果となりました。 どれも適切な値が定義できてますね! 補足 行位置及び列番号は直値で指定しています。タイトルの文字列をキーとして検索する方法やgetNextDataCellメソッドなどでセル位置を取得する方法も検討しましたが、タイトル名が変更された、意図しない文字列が存在していたため想定外のセル位置が取得された、といったケースを考慮してより確実性の高いコーディングにしています。そのため、対象の行・列番号や実行範囲は任意に指定できる反面、行・列が追加・削除された場合、別シートに対して実行したい場合などは再定義する必要があります。 3.比較対象の取得 続いて、体裁修正時に比較する項目の値を取得していきます。 今回は、スプレッドシートから値を直接取得するのではなく、あらかじめ全ての値を配列に格納し、その各要素を比較するようにコーディングしています。 ※理由は別章「実行結果」に記載。 let primaryItemAry = fixSheet.getRange(firstRowUpper, primaryItemCol, fixRange + 1, 1).getValues().flat(); let secondaryItemAry = fixSheet.getRange(firstRowUpper, secondaryItemCol, fixRange + 1, 1).getValues().flat(); let tertiaryItemAry = fixSheet.getRange(firstRowUpper, tertiaryItemCol, fixRange + 1, 1).getValues().flat(); ※「fixRange」は、「全体の項目数 – 1項目」となっているので、ここでは不足している「1」を加算しておきます。 変数の戻り値 「大項目(primaryItemAry)」を例に配列の中身を確認してみると、下図の結果となりました。 「中項目」「小項目」でも同様に、該当する全ての項目が格納されています。 次節「4.体裁修正処理」では、これらの要素を上から順に2つずつ参照していくことで、スプレッドシート上の上下列も間接的に比較できるようになっています。 補足 今回は、「大項目」「中項目」「小項目」の各列ごとに一次元配列に格納するようにコーディングしていますが、列数が多くなる場合などは以下のようにまとめて同じ配列に格納する方法でも良さそうです。 その際、要素指定には注意が必要です。 let itemAry = fixSheet.getRange(firstRowUpper, primaryItemCol, fixRange + 1, 3).getValues(); 4.体裁修正処理 修正時に必要となる各値を定義・取得できたところで、体裁修正処理に入ります。 制御処理 別章「要件定義」で整理した内容に基づき、for文によるループ実行で各行・列の体裁を修正していきます。 ループ数の条件は「fixRange(実行範囲)」を指定します。 for (let i = 0; i < fixRange; i++) { ここで定義した変数「i」は、以降の体裁修正処理でも使用します。比較対象となる配列要素や修正対象となる行位置に「i」を指定、または加算することで、ループ時のインクリメントに追従して修正処理の対象が変化する制御となります。 「大項目」の体裁修正 if文で「大項目」の上下行の値を比較し、その判定結果を元に体裁修正する内容を分岐させます。 if (primaryItemAry[i] === primaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, primaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, primaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, primaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; 同じ値の場合 : if 大項目[ 上行 ] = 大項目[ 下行 ]  ・文字色設定:setFontColor   文字色:#cccccc(グレー) ・罫線設定:setBorder   上部:FALSE(描画しない) ※上部罫線が引かれていた場合は削除   左部:TRUE(描画する) ※左部罫線が引かれていなかった場合を想定   下部:null(何もしない)   右部:null(何もしない)   水平:null(何もしない)   垂直:null(何もしない)   罫線色:#000000(黒)   罫線スタイル:SOLID(細い実線) 同じ値以外の場合 :else  ・文字色設定:setFontColor    → コード記述なし(何もしない) ・罫線設定:setBorder   上部:TRUE(描画する) ※上部罫線が引かれていた場合は上書き   左部:TRUE(描画する) ※左部罫線が引かれていなかった場合を想定   下部:null(何もしない)   右部:null(何もしない)   水平:null(何もしない)   垂直:null(何もしない)   罫線色:#000000(黒)   罫線スタイル:SOLID(細い実線) 「中項目」の体裁修正 体裁修正する内容は「大項目」と同じですが、判定条件に「大項目同士が同じ場合(primaryItemAry[i] === primaryItemAry[i + 1] && )」を含めています。 if (primaryItemAry[i] === primaryItemAry[i + 1] && secondaryItemAry[i] === secondaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, secondaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, secondaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, secondaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; 「小項目」の体裁修正 こちらも体裁修正する内容は「大項目(中項目)」と同じですが、判定条件に「大項目同士かつ中項目同士が同じ場合(primaryItemAry[i] === primaryItemAry[i + 1] && secondaryItemAry[i] === secondaryItemAry[i + 1] && )」を含めています。 if (primaryItemAry[i] === primaryItemAry[i + 1] && secondaryItemAry[i] === secondaryItemAry[i + 1] && tertiaryItemAry[i] === tertiaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; 以上が各コーディング内容となります。下記にまとめとして、全体のコーディング+スクリプト実行時間を測定する処理を含めたソースコードを記載しています。少しでもご活用いただけたらと思います。 5.ソースコード /** * 関数名 :TestSheetFix * 内容 :スプレッドシートで作成したテスト項目書の体裁を修正する * 修正対象:C列[4行目~最終行]:大項目(primaryItem) *    D列[4行目~最終行]:中項目(secondaryItem) *    E列[4行目~最終行]:小項目(tertiaryItem) * * ※ 流用する際は、テスト項目書に応じて「先頭行の定義」「最終行の定義」「各列の定義」を再定義して下さい */ function TestSheetFix() { //実行時間計測用:開始 const startTime = new Date(); //スプレッドシート・項目シートの取得 const activeSheet = SpreadsheetApp.getActiveSpreadsheet(); const activeSheetName = SpreadsheetApp.getActiveSheet().getName(); const fixSheet = activeSheet.getSheetByName(activeSheetName); //先頭行の定義 let firstRowUpper = 4; let firstRowLower = firstRowUpper + 1; //最終行の定義 let lastRow = 23; //実行範囲の定義 let fixRange = lastRow - firstRowUpper; //列番号の定義 let primaryItemCol = 3; let secondaryItemCol = primaryItemCol + 1; let tertiaryItemCol = primaryItemCol + 2; //比較対象の取得 let primaryItemAry = fixSheet.getRange(firstRowUpper, primaryItemCol, fixRange + 1, 1).getValues().flat(); let secondaryItemAry = fixSheet.getRange(firstRowUpper, secondaryItemCol, fixRange + 1, 1).getValues().flat(); let tertiaryItemAry = fixSheet.getRange(firstRowUpper, tertiaryItemCol, fixRange + 1, 1).getValues().flat(); //体裁修正処理 for (let i = 0; i < fixRange; i++) { //「大項目」の体裁修正 if (primaryItemAry[i] === primaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, primaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, primaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, primaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; //「中項目」の体裁修正 if (primaryItemAry[i] === primaryItemAry[i + 1] && secondaryItemAry[i] === secondaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, secondaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, secondaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, secondaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; //「小項目」の体裁修正 if (primaryItemAry[i] === primaryItemAry[i + 1] && secondaryItemAry[i] === secondaryItemAry[i + 1] && tertiaryItemAry[i] === tertiaryItemAry[i + 1]) { fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setFontColor('#cccccc') fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setBorder(false, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) } else { fixSheet.getRange(firstRowLower + i, tertiaryItemCol).setBorder(true, true, null, null, null, null, '#000000', SpreadsheetApp.BorderStyle.SOLID) }; }; //実行時間計測用:終了 const endTime = new Date(); //実行時間(s)の算出 const runTime = (endTime - startTime) / 1000; //ログ出力 console.log(runTime); }; 実行結果 1.実行結果 それでは、以下のテスト項目書に対してコードを実行し、結果を確認してみましょう! 実行前のテスト項目書 ※項目内容は別章「はじめに」のパターンA・Bと同じですが、下記の通り少し細工をしています。 罫線  ・#6:「大項目」の左部に罫線が引かれていない  ・#7(#8):「中項目」の下部(上部)に罫線が引かれていない  ・#12(#13):「中項目」の下部(上部)に太字の罫線が引かれている  ・#18:「小項目」の左部に赤い罫線が引かれている  ・先頭行上部:項目を区別するために太字の罫線となっている  ・最終行下部:項目を区別するために太字の罫線となっている 文字色  ・#16:「小項目」が赤字になっている 補足 上記の「罫線」は体裁上で特に意味をなしておらずテスト設計者による誤記だと想定し、修正対象としています。ただし、先頭行上部と最終行下部の太字の罫線については意図した描画であるため、こちらは修正対象としません。また「文字色」については、テスト設計者が項目内容に対する注記やテスターへの補足といった意図した設定の可能性があるため、こちらも修正対象としていません。 果たして、結果は如何に・・・? 実行後のテスト項目書 期待通りの体裁となりました! 罫線及び文字色が各条件に従って修正されており、今回の要件通りとなっています。 実行時間 20項目程度だと約0.6秒で実行できました。はやい! 補足 GAS内で一発で実行できたため、実行後のUndo(Ctrl + Z)・Redo(Ctrl + Y)も一発で対応可能でした。修正結果を戻したい場合や意図しない修正を入れてしまった場合などでも、一発で手戻りできます。 2.ハマりポイントと改善策 最後に、実装時にハマったポイントとその改善策を記載しておきます。 当初は、体裁修正処理で比較対象となる上下の値をスプレッドシートから直接取得する方法で実装していたのですが、どうしても実行速度が遅くなってしまう問題が起きていました。 調べたところ、関数やメソッドの実行対象にスプレッドシートなどGAS以外のサービスを指定した場合、実行時にAPI連携が発生するようです。そのため、上述のようにfor文中にgetValueメソッドを記述し、かつ取得元にスプレッドシートを指定すると、ループするたびにリクエスト回数が増加してしまい、結果としてスクリプト実行時間が伸びてしまっていたことが遅延の原因でした(当然と言えば当然でした…)。 なので、事前に全ての比較対象となる値を一括で配列に格納し、体裁修正処理でこれらの要素を参照することで、比較時の処理をGAS内で完結できるように改善しました。 参考までに、改善前後のイメージ図と500項目に対して体裁修正したときの実行時間を以下に記載しています。 実行イメージ   実行時間  改善前    419秒=約7分で完了しました。手動作業よりは多少早いくらいでしょうか…?  改善後     約7.6秒で完了しました!かなり良化しました◎ おわりに 今回ご紹介した方法であれば、500項目でも7.6秒程度で体裁修正できたため、作業コストが大幅に削減できるのではないでしょうか(項目数が多ければ多いほど効果的!)。 ただし、本記事ではあくまでも仮のテスト項目書に対するサンプルコードを解説しているため、ご使用いただく際は対象ドキュメントの目的や用途に応じて適宜カスタマイズして頂ければと思います。 また、こうした「GAS × スプレッドシート」といったサービスを上手く組み合わせて業務を適切に自動化・効率化し、作業をドンドン捗らせちゃいましょう! The post GoogleAppsScriptを使ってテスト項目書の体裁を一発で整える first appeared on Sqripts .
アバター
この連載は、登場して20年が過ぎ、成熟期を迎えつつある「アジャイル開発」を解説します。アジャイル開発については、世の中にたくさんの書籍や情報があふれていますが、アジャイルコーチとして10年以上の現場経験をもとに、あらためて学び直したい情報を中心にまとめていきます。 第2回目のテーマは、「アジャイルマニフェスト」です。 この内容はUdemyで公開しているオンラインコース「 現役アジャイルコーチが教える!半日で理解できるアジャイル開発とスクラム 入門編 」の内容を元にしています。 アジャイルマニフェスト アジャイルソフトウェア開発宣言。通称アジャイルマニフェスト アジャイルマニフェストは、わずか10行のWebページです。アジャイル開発やそれに関連するプロセスを学んだり、実践していくと、マニフェストの内容をたびたびふりかえるケースが増えます。それぐらいアジャイル開発の本質をついた内容になっています。特に重要とされる部分は、2段落目にある4つの価値観です。これを読みやすく書き直すと以下になります。 プロセスやツールよりも 個人と対話 に価値をおきましょう。 包括的なドキュメントよりも 動くソフトウェア に価値をおきましょう。 契約交渉よりも 顧客との協調 に価値をおきましょう。 計画に従うことよりも 変化への対応 に価値をおきましょう。 よく「アジャイル開発はドキュメントを重要視しない」と解釈している人がいますが、それは間違いです。ここで伝えたいことは、上記文章の通り、「〜よりも〜に価値をおきましょう」なので、どっちも重要。ただし、しいていうなら後者に価値をおいていきましょうということになります。 次に、太字の部分を抜き出してみましょう。 個人との対話 動くソフトウェア 顧客との協調 変化への対応 アジャイル開発に取り組んでいく場合、ふりかえりなどのタイミングでこの4点に価値をおけているか?を確認するといいでしょう。そうすることで、アジャイル開発が向かおうとしている方向を確認するコンパスのように使えるはずです。 アジャイルソフトウェアの12の原則 アジャイル宣言の背後にある原則 アジャイルマニフェストの4つの価値の下には、『アジャイルソフトウェアの12の原則』と書かれたリンクがあります。アジャイルマニフェストは4つの価値が目立ちますが、このアジャイルソフトウェアの12の原則も重要な内容になっています。 4つの価値は、17人の開発方法論者が合意できた価値観でしかありませんが、原則は、価値よりも具体的な内容が書かれているため、指針になります。では、その内容を見ていきましょう。 1. 顧客満足を最優先し、価値のあるソフトウェアを早く継続的に提供します アジャイルチームは価値の最大化を常に考えています。さらに、顧客満足を優先した意思決定を行っていきます。 なにか判断が必要なときに、顧客満足を最優先にできているか? アジャイルコーチであれば、価値あるソフトウェアを早く継続的に提供できているか? チームに問いかけていきます。 2. 要求の変更はたとえ開発の後期であっても歓迎します。変化を味方につけることによって、お客様の競争力を引き上げます 4つ目の価値である「変化への対応」に紐付いた原則です。アジャイル開発は変化への対応を重視した方法なので、変化に弱くなっている場合は、自分たちのやり方を根本的に見直さなければなりません。 とはいえ、何でも変化に対応できるわけではありません。開発の後期で変化を受け入れるなら、それに伴い再計画が必要になったりします。何かを受け入れるなら、何かを捨てなければならなくなるというシンプルな考え方です。 3. 動くソフトウェアを、2-3週間から2-3ヶ月というできるだけ短い時間間隔でリリースします 「開発の速さ」に関する原則です。アジャイル開発は長期的な開発なのですが、小さく期間を区切って、リリースを繰り返しながら積み上げていく開発になります。 もし、仕事を小さくするのが難しい場合は、アジャイル開発に適したシステムではないかもしれません。アジャイル開発に取り組む前に、リアーキテクチャのような仕事を小さくする方法を検討するといいかもしれません。 4. ビジネス側の人と開発者は、プロジェクトを通して日々一緒に働かなければなりません アジャイルチームを組成する場合、もっとも難易度が高いのがこの原則かもしれません。とくにビジネスと開発が組織的に分かれている場合は、なかなか対策を打ちにくい部分でもあります。 ただ、ビジネスでも開発でも、同じゴールを目指すのであれば、この原則はなんとか実現したいものです。はじめは難しくとも、 まずはMTG時間を使ってコミュニケーションの場を作る 開発チームのにビジネスの出張席を作る(もしくはその逆) 同じ場所で働く 専用の部屋で働く・・・ と徐々にやれることをやっていく形にするといいと思います。 5. 意欲に満ちた人々を集めてプロジェクトを構成します。環境と支援を与え仕事が無事終わるまで彼らを信頼します よく、「アジャイル開発は優秀な人じゃないとできないのではないか?」と質問されますが、自分なら「意欲に満ちた人が必要」と答えます。 もちろん優秀な人に集まって欲しいとは思いますが、必須条件ではないと考えているからです。 6. 情報を伝えるもっとも効率的で効果的な方法はフェイス・トゥ・フェイスで話をすることです 4つの価値にある「個人との対話」に紐づく原則です。 最近はオンラインでの仕事が広まり、ツールも便利になったので、オンラインのコミュニケーションがやりやすくなってきました。少し前、筆者は久しぶりにオフラインでMTGをやったのですが、オンラインと比べて、ダントツにコミュニケーションが取りやすく感じました。 いくらツールが発達したとしても、そのツールをうまく活用したとしても、オフラインのコミュニケーションにまさるものはないのかもしれません。 7. 動くソフトウェアこそが進捗の最も重要な尺度です 4つの価値にある「動くソフトウェア」に紐づく原則です。アジャイルチームの成果は、動くソフトウェアで測られます。 整備されたドキュメントやテスト結果をまとめたレポートも重要ですが、動くソフトウェアほどシンプルに成果を確認できる手段はありません。 8. アジャイル・プロセスは持続可能な開発を促進します。一定のペースを継続的に維持できるようにしなければなりません この文のポイントは、「持続可能な開発」です。つまり、アジャイルチームはムリ・ムダ・ムラを避けていかなければなりません。 そうしなければ、どこかでムリがたたり、持続可能な開発ができなくなるでしょう。 9. 技術的卓越性と優れた設計に対する不断の注意が機敏さを高めます。 読み取るのが難しい文章です。原文を DeepL で訳してみましょう。 Continuous attention to technical excellence and good design enhances agility. 優れた技術と優れたデザインへの継続的な配慮が、アジリティを高めています。 アジャイル開発はすばやく開発する方法ではありますが、技術やデザイン(設計)を放置しているわけではありません。優れた技術やツールがアジリティ(俊敏性)を生み出すのは当然ですし、よい設計もアジリティを上げるために必要な要素になります。 10. シンプルさ(ムダなく作れる量を最大限にすること)が本質です。 これはトヨタの考え方が現れた原則です。スクラムを見ると、まさにこの原則に従っているように感じます。 11. 最良のアーキテクチャ・要求・設計は、自己組織的なチームから生み出されます。 この原則も読み取りにくい内容です。そういうときは原文をDeepLに通してみましょう。 The best architectures, requirements, and designs emerge from self-organizing teams. 最適なアーキテクチャ、要件、設計 は、自己組織化したチームから生まれる。 興味深いのは、アーキテクチャを考えるのは「だれか」ではなく、「チーム」であることだと思います。チームを重要視するアジャイル開発らしい原則です。 日本語では「生まれる」となっていますが、原文はemerge (【自動】 表面に出てくる、現れる、出現する、浮かび出る)なので、ベストなアーキテクチャはチームから自然に生まれてくる・・・というニュアンスになります。 12. チームがもっと効率を高めることができるかを定期的に振り返り、それに基づいて自分たちのやり方を最適に調整します。 最後はふりかえりの重要性です。「アジャイル開発ができない場合でも、ふりかえりは絶対やったほうがいい」と思います。 アジャイルマニフェスト、12の原則の意味 以上が、アジャイルマニフェスト、アジャイルソフトウェアの12の原則の解説です。 4つの価値については、若干ふんわりした表現になっていますが、原則を一緒に読み解いていくと、具体的にどうあるべきかが見えてきます。 世の中にはたくさんのアジャイル開発にまつわる本や記事がありますが、それらが行き着く先はアジャイルマニフェストや12の原則です(この記事もそうだと思います)。 アジャイルに正しさを求めると、原理主義的になり弊害が生まれやすいのですが、アジャイルチームの人であれば、自分たちの現状を、価値や原則に照らしあわせることで、自分たちの現在位置や、理想の状態がわかるようになるはずです。 The post 第2回 声に出して読みたいアジャイルマニフェスト first appeared on Sqripts .
アバター
こんにちは、QAエンジニアのカンパチロックです。 今回は、テストフェーズにおいてQAの価値を向上させる方法の1つとして、分散トレーシングおよびその標準規格であるOpenTelemetryについて説明します。これにより、システム内で発生する問題をより迅速かつ正確に特定し、開発プロセスをより迅速かつ効率的に進めることができます。 分散トレーシングとは まず、分散トレーシングにという用語について皆さん聞いたことはありますでしょうか? 商用の製品としては、Dynatrace、NewRelic、DatadogなどのAPM(Application Performance Management)製品に実装されている為、こちらの名前を聞いた事がある方もいらっしゃるかもしれません。 分散トレーシングの概要は、ユーザーからのリクエストに伴う様々なサービス呼び出しやデータストアへのアクセスなど、一連の処理(トランザクション)をパラメータやログと組み合わせて追跡・管理することです。これにより、従来のログ管理では分析に時間がかかる問題の原因を特定するプロセスが劇的に高速化されます。分散トレーシングの利点は、まさにこの迅速な問題解決能力にあります。 特にマイクロサービス環境下では、多くのサービスが複雑な関係性を持って連携しており、問題発生時に、問題の発生元となるサービスの特定に多くの時間を要するリスクがあり、その対策としての分散トレーシングの導入についても注目されております。 分散トレーシングのOSSとして有名なJeagerのサイトでは、分散トレーシングで収集したデータの可視化イメージとして下記のようなイメージが掲載されています。 左側のグラフのように、取得したデータからサービス間の連携状況を可視化したり、右側のウォータフォールチャートのように、ユーザのリクエストから発生する一連の処理について、どのサービスでどの程度の時間が掛かっているかや、処理実施時のパラメータ情報やエラー発生時のエラーログなどをトランザクション毎に確認できることができます。これらの可視化機能により、システム全体のパフォーマンスや問題の特定が容易になります。 引用元:  https://www.jaegertracing.io/docs/1.33/architecture/#span 詳細については、以下のサイトで説明されていますので、ご参照下さい。 分散トレーシングとは メリット、仕組みなどを解説 | Splunk ディストリビューティッド (分散) トレーシングの概要 OpenTelemetryについて ここからは、より具体的な内容として、OpenTelemetryについて説明します。 OpenTelemetryは、分散トレーシングの共通規格を提供するプロジェクトで、2019年にそれまで別々の規格であったが統合されて誕生しました。これにより、分散トレーシングの標準化が一層進んでいます。 分散トレーシングにおいて、ベンダーロックインが課題となっていました。これは、別のAPM製品に乗り換える際に、新しいAPM製品に合わせたエージェントの再配置やソースコードの修正が必要だったためです。しかし現在、多くのAPM製品がOpenTelemetry規格に対応しているため、APM製品の乗り換え時のインパクトが大幅に軽減されています。極端な例として、接続先サービスの切り替えのみで乗り換えが完了するケースもあります。 今後、分散トレーシングを導入する際には、標準規格であるOpenTelemetryについて理解を深めることが重要であると考えられます。これにより、より効率的なトレーシングシステムの構築や、さまざまなAPM製品との互換性が向上し、将来的な拡張性も確保されます。 OpenTelemetryで出来ること OpenTelemetryでは、主要な取得情報としてTrace、Metrics、Logの3要素があります。言語ごとに対応状況は異なりますが、以下にそれぞれの要素について簡単に説明します。 Trace:ユーザのリクエストを起因とした各種サービスでの処理内容や処理時間を記録したもの Metrics:サービス実行時の各種統計情報(サービスの実行回数やレスポンスの平均値など) Log:サービスで発生したイベントを記録したもの(Traceと紐付け可能) 詳細については、OpenTelemetryの Signalsドキュメント を参照してください。 なお、大規模なアクセスが想定されるサービスの分散トレーシングにおいて、全てのリクエスト情報を取得・保存すると、分散トレーシングの仕組み自体が負荷のボトルネックとなる可能性があります。そのため、一般的には取得・保存するリクエストをサンプリングします。ただし、サンプリングされたTrace情報からは全体の統計情報を取得できないため、別途Metrics機能が提供されています。 OpenTelemetryでは、将来的にProfilingのサポートを追加することが計画されており、コードベースでの実行機能や処理時間をより詳細に取得できるようになる可能性があります。 https://github.com/open-telemetry/oteps/issues/139 OpenTelemetry規格とは別に、Apache SkyWalkingのような一部のAPM製品では、すでにプロファイル情報をトレーシングの一部として組み込む機能が実装されています。 SkyWalking Python Agent Supports Profiling Now OpenTelemetryでは、各言語用のライブラリが提供されており、多くの場合、自動計装(自動インストゥルメンテーション)によってアプリケーションへのトレーシング機能の導入が容易になっています。自動計装により、手動でコードに計測ポイントを追加することなく、既存のアプリケーションに対してトレーシングやメトリクスの収集が可能となります。言語ごとの対応状況や自動計装の詳細については、以下のリンクを参照してください。 また、JavaScriptに関しては、Node.js用とBrowser用のライブラリが用意されており、ブラウザ側からTrace情報を送信する事も可能となっています。 Instrumentation OpenTelemetryを活用した可視化のレベル 上記で説明したTrace、Metrics、Logの情報を各サービスから収集することにより、システム全体の可視化が実現可能です。ここでは、どのようなレベルの可視化が可能かを検討してみたいと思います(あくまで可能性を示すものであり、現時点では実現が難しい事柄も含まれるかもしれません)。 前項でも少し触れましたが、OpenTelemetryのJavaScriptライブラリには、ブラウザ用のライブラリも提供されています。これにより、ブラウザから送信された情報をトレーシングのエンドポイントとして扱うことが可能です。 npm: @opentelemetry/auto-instrumentations-web さらに、リクエストだけでなく、ユーザの操作(フォームへの入力やボタンのクリックなど)もトレーシングできるため、ブラウザ上でユーザが行った操作からバックエンドの処理までの一連の動作をトレースすることが可能です。これらの機能を利用することで、エンドユーザーの体験とシステム全体のパフォーマンスをより詳細に把握することができます。 これらを組み合わせて得られる情報のイメージは、以下のような形になるでしょう。 ユーザがトップ画面で検索キーワードを入力し、検索ボタンを押下した。 検索ボタンの押下により、XXX APIのリクエストが発生し、その際の検索パラメータはXXXだった。 バックエンドサーバがリクエストを受け付け、外部サービスBのAPIを実行した。その際のパラメータはYYYだった。 サービスBではデータストアに検索クエリを発行し、取得した結果をもとにバックエンドサービスにレスポンスを返した。 バックエンド側で未処理のエラーが発生した。その際のスタックトレース及びエラーメッセージはZZZだった。 従来のログ管理では、個々のサービスのログをそれぞれ分析し、原因箇所を特定する必要がありましたが、OpenTelemetryを各サービスに実装することにより、上記のような情報取得が可能になります。 OpenTelemetryの各種ライブラリが提供するAuto Instrumentation機能を活用することで、主要なトレース情報(外部サービスのAPIコールやデータストアへのクエリ実行など)は簡単な設定とライブラリのインストールだけで実現可能です。これにより、個別のプログラムを修正してトレースを実装する必要が大幅に減り、効率的な可視化が実現できます。 分散トレーシングとQAについて ここまで、分散トレーシングおよびその標準規格であるOpenTelemetryの概要について説明させていただきましたが、我々AGESTのようなQAを主業務とする企業において、これらの機能がどのように活用できるかを考察してみたいと思います。 分散トレーシングは、運用目的のツールや性能テストでのボトルネック調査といったイメージが強いですが、それだけではなく、その導入の容易さや、原因調査能力の高さや、収集情報の有用性から、一般的なテストにおいてもバグ発生時の原因究明を迅速に行える可能性もあります。このように、分散トレーシングはテストプロセスにおいても重要な役割を果たすことができるのです。 従来、QAと開発の関係では、不具合が発生した場合、QA側が発生手順、発生日時、再現率などの情報を開発者に伝え、開発者がログ解析や原因調査を行うのが一般的でした。しかし、分散トレーシングの導入によって、QA側が開発者により詳細な情報を提供できるようになりますし、開発の実態やサービス内容をより深く理解した上でのQA実施が可能となります。 この変化によって、従来のQAの枠組みを超えた、新しい形のQAサービスが提供できる可能性があります。 最後に 以上、分散トレーシングとQAについてでした。 分散トレーシングは、現代の複雑なシステム開発において欠かせない技術の一つです。QAの観点から見ると、テスト工程においてトレーシング機能を活用することで、システムの挙動を正確に把握し、品質管理をより効果的に行うことができます。 しかし、この技術を活用するためには、開発チームとの密なコミュニケーションが必要です。開発チームと共に、テスト戦略を練り上げることが、高品質なソフトウェアの開発につながります。 今後も、常に最新のテスト技術に目を向け、学び続けることが大切です。皆さんもぜひ、分散トレーシングをはじめとする最新のテスト技術を取り入れ、より高度な品質管理に取り組んでみてはいかがでしょうか The post 分散トレーシングの活用による次世代のテストを考える first appeared on Sqripts .
アバター
現代のソフトウェア開発では、競争力を維持し、顧客ニーズに迅速に対応するために、より短いスパンでのリリースが求められるようになりました。従来の開発手法ではこれが難しいとされており、こうした課題に対応するために注目されているのがDevOpsです。 この記事では、初級者エンジニア向けに、DevOpsの基本知識やアジャイル開発との違い、DevOpsのライフサイクルや導入方法まで、詳しく解説していきます。DevOpsに興味を持っている方や、DevOpsを導入するメリットを知りたい方は、ぜひこの記事を読んでみてください。 DevOpsとは? DevOps(デブオプス)は、ソフトウェア開発における開発者を意味する(Development)と運用者を意味する(Operations)を組み合わせた造語です。DevOpsは、開発チームと運用チームが協力して、一つのチームとして、スピーディにソフトウェアを開発し、品質や生産効率を高めることを目的としています。 従来の開発チームと運用チームは、役割が異なるために対立することがありました。一般的に、プログラムを作成する開発チームと、システムの運用を担当する運用チームに分かれて作業を行います。開発チームの役割は、競合他社との競争力を得るため、システムに新しい機能を追加することであり、運用チームの役割は、安定したサービスを提供し続けることです。しかし、新しい機能を追加したい開発チームに対し、運用担当者はシステムの安定稼働を優先するため、機能追加に慎重になることがありました。 DevOpsはこのような問題を解決するために、開発チームと運用チームが協力して、一つのチームとして開発にのぞむための手段と言えます。開発と運用の間の壁が取り払われることで、効率的かつ効果的なソフトウェア開発と運用が実現されます。 DevOpsの基本 DevOpsは、開発チームと運用チームが協力してソフトウェアを作ることを目指すため、以下のような考え方を基本とします。 ソフトウェア開発ライフサイクルの自動化 共同作業とコミュニケーションの向上 継続的な改善と無駄の最小化 ユーザーニーズの重視とフィードバックループの最短化 これらの基本原則を理解した上で、開発・運用の各プロセスを自動化することで、効率的かつ効果的なソフトウェア開発と運用を実現し、継続的に改善することができます。 DevOpsが重要な理由 DevOpsの重要性は、開発と運用のコラボレーションを促進し、開発から運用までの一貫性を確保することにあります。また、自動化ツールを活用することで、作業の効率化と品質向上を実現できます。さらに、DevOpsは迅速なビジネス対応とイノベーションの促進にも寄与します。これらの理由から、DevOpsは現代のソフトウェア開発において、必要不可欠な要素です。 DevOpsとアジャイル開発の違い DevOpsとアジャイル開発は、ともにソフトウェア開発において重要な手法ですが、それぞれのコンセプトは異なる側面があります。 アジャイル開発の特徴は以下のとおりで、どちらかというと開発に注力した考え方をしています。 要件や仕様の変更を積極的に受け入れるようにしている 設計・開発・リリースのような工程でできるだけわけずに、小さな機能ごとの開発を短い期間内で繰り返し行っていく コミュニケーションを重要視し、自己組織化されたチーム 一方で、DevOpsは、先ほどDevOpsの基本で説明した4点の考え方を特徴としており、運用と開発のつなぎこみに注力する側面が強いです。 つまり、アジャイル開発はソフトウェア開発の具体的な手法であり、DevOpsはソフトウェア開発と運用の手法となります。 DevOpsとCI/CDとの違い DevOpsとCI/CDは、ときどき混同されがちですが、それぞれ異なる概念であり、同時に密接な関係があります。 CI/CDはContinuous Integration(継続的インテグレーション)とContinuous Delivery(継続的デリバリー)の略称で、ソフトウェア開発における自動化の実践です。 CI/CDによる自動化は、DevOpsの考え方と相性が良く、効率的かつ効果的なソフトウェア開発と運用を実現するために、DevOpsアプローチの中でCI/CDが活用されることが多いです。つまり、CI/CDはDevOpsの実践において重要なツールとして機能し、両者は相互に補完しあう関係にあります。 DevOpsのライフサイクル DevOpsはソフトウェア開発と運用に関わる考え方ですが、その具体的なプロセスはどうなっているでしょうか?DevOpsのライフサイクルには、計画・コーディング・ビルド・テスト・リリース・デプロイ・運用・モニタリングの8つのステップがあります。DevOpsのライフサイクルを正しく実施することで、開発チームと運用チームが協力し、より迅速かつ信頼性の高いソフトウェア開発を実現することができます。 以下に各ステップの概要を説明します。 計画(Plan) DevOpsのライフサイクル最初のステップは計画です。このステップでは、開発チームと運用チームが協力して、ソフトウェアの要件定義や開発計画を策定します。計画ステップでは、開発と運用の間でのコミュニケーションが重要であり、双方が協力して開発計画を策定することが大切です。 コード(Code) 計画ステップの次はコーディングステップです。このステップでは開発チームがプログラムのコードを開発し、ソースコード管理システムにコードを格納します。単体テスト、コードレビューなどの手順を経て、コードを完成させます。 ビルド(Build) コーディングステップが完了したら、次のステップはビルドです。ビルドステップでは、開発チームがソースコードをビルドして動作可能なアプリケーションを作成します。自動化ツールやクラウドサービスを活用して、ビルドを迅速かつ安全に行います。 テスト(Test) ビルドしたアプリケーションに不具合がないかを確認するステップです。ここでは、開発チームがアプリケーションをテストし、バグを特定して修正します。テストステップでは、自動テスト、手動テスト、セキュリティテストなどの手順を経て、ソフトウェアの品質を確認します。 リリース(Release) リリースステップでは、ソフトウェアの新しいバージョンが完成し、デプロイの準備が整います。リリース管理ツールを使用して、ソフトウェアの異なるバージョンを管理し、必要に応じてロールバックできるようにします。 デプロイ(Deploy) リリースされたアプリケーションやソフトウェアの新しいバージョンを実際の本番環境に配置します。デプロイの工程では、リリースされたバージョンのアプリケーションが実際のサーバー、クラウド環境、または他のインフラストラクチャに配置され、本番環境での動作が確認されます。 運用(Operate) 運用ステップは、ユーザーサポートやトラブルシューティング、システムメンテナンスを実施し、システムを安定稼働させます。 モニタリング(Monitor) モニタリングステップでは、運用チームがシステムの稼働状況を監視し、問題が発生した場合には、迅速に対応します。 DevOpsのライフサイクルは、開発と運用を連携させ、自動化することを重視したプロセスです。この方法により、ソフトウェア開発と運用のパフォーマンスと品質を向上させることができます。 DevOpsの開発手法 DevOpsの開発手法は、ソフトウェア開発プロセスにおいて、開発チームと運用チームが協力して、アプリケーションの開発・テスト・デプロイ・運用を継続的に改善するための手法です。 DevOpsの開発手法には、以下の項目があります。 継続的インテグレーション 継続的デリバリー 継続的デプロイメント コミュニケーションと共同作業 継続的フィードバック これらの手法を正しく理解し、導入することで、開発チームと運用チームがより密接に連携し、効率的かつスムーズなアプリケーションの開発・テスト・デプロイ・運用が可能になります。 継続的インテグレーション 継続インテグレーションは、コードの変更を共有リポジトリにマージした後、自動化されたビルドとテストを実行することで、問題を早期発見することができ、品質を向上させるための手法です。この手法により、開発者はコードの変更に伴う不具合を迅速に解決し、品質の高いソフトウェアを提供できるようになります。また、テストを自動化することで開発者は時間と手間を省くことができるので、より大規模なプロジェクトでも効率的に作業できます。 継続的デリバリー 続的デリバリーは、ソフトウェアのリリースプロセスを自動化し、常にリリース可能な状態を保つ手法です。この手法は、アプリケーションのリリースに必要な準備を自動化することでリリースの速度と安全性を向上させるだけでなく、品質の向上、コストの削減、チームメンバーのストレス軽減などのメリットもあります。 ただし、リリース自体は人が手動で実行する必要があるため、デプロイプロセスの設計と慎重なテストが必要です。 継続的デプロイメント 継続デプロイメントとは、ソフトウェア開発で変更を行うたびに、リポジトリから本番環境やテスト環境に自動的にリリースする手法です。この手法により、リリースのスピードを向上させることができます。継続的デプロイメントでは、ビルド、テスト、デプロイが自動化されているため、開発チームや運用チームの負担を軽減し、素早いリリースを実現できます。 継続的デプロイメントと継続的デリバリーの違いは、継続的デリバリーは本番環境にリリースする前に、人の承認作業が必要になる点です。一方、継続的デプロイメントでは変更が行われたらすぐに本番環境にリリースされるため、より迅速なリリースが可能です。 このように、継続的デプロイメントは、開発者がより頻繁に変更をリリースできるため、ユーザーのフィードバックをより早く反映することができます。 コミュニケーションと共同作業 DevOpsの成功には、運用チームと開発チームの共同作業が不可欠であり、そのためには組織内でのコミュニケーションが欠かせません。具体的には、チャットアプリやプロジェクト管理ツールなどのDevOpsツールを使用してリアルタイムで情報共有やコミュニケーションを促進することが重要です。例えば、SlackやMicrosoft Teamsなどのチャットアプリは、リアルタイムでチームメンバーと瞬時にコミュニケーションを取ることができ、問題点を素早く共有し、対応することができます。また、プロジェクト管理ツールの例として、Azure DevOpsやJiraなどがあり、タスクの進捗状況の共有やプロジェクト全体の進捗管理を行うことができます。これらのツールを活用することで、タスクの進捗状況や問題点の共有がスムーズになり、組織全体が目標に向かってより密接に連携できるようになります。 継続的フィードバック 継続的にフィードバックを得ることで、顧客のニーズに合わせた製品の改善が可能になります。具体的には、プロトタイプやモックアップのように開発の早期段階からフィードバックを獲得する方法や、A/Bテストやカナリヤリリースのように本番稼働中のシステムからフィードバックを獲得する方法があります。 このように、継続的にフィードバックを得ることで、開発チームは製品を改善し、より高品質な製品を提供できるようになることから、顧客との信頼関係を築くことができるようになります。 DevOpsを導入するメリット DevOpsはソフトウェア開発と運用のパフォーマンスと品質を向上させることができますが、その具体的なメリットは何でしょうか?DevOpsのメリットは以下のようなものがあります。 開発スピードの向上 DevOpsの考え方やプラクティスを取り入れることにより、開発と運用のプロセスを効率化し、自動化を促進することができます。これにより、開発者はより迅速にアプリケーションを開発することが可能になります。また、DevOpsにより、開発者と運用者がより密接に連携できるため、開発者はより早い段階でフィードバックを受け取ることができます。 信頼性の向上 自動化されたテストやデプロイメントプロセスを通じて、システムの品質を向上させることができ、信頼性の高い製品を提供できます。 生産性の向上 DevOpsの導入により、開発者と運用者はより迅速にシステムを開発・デプロイすることができます。またリリースまでのプロセスを迅速化することで、ユーザーのフィードバックを早く反映させることができ、生産性を向上させることができます。 共同作業性の向上 DevOpsツールにより、開発チームと運用チームがより密接に連携することができるので、コミュニケーションの障壁を取り除くことができます。またチーム全体でシステムの状態を把握できるため、共同作業性を向上させることができます。 拡張性の向上 DevOpsの考え方では、インフラストラクチャもアプリケーションコードと同様にコードで管理することが推奨されます。この手法をInfrastructure as Codeと呼び、インフラをコードで定義することで、標準化されたパターンでリリース、更新、複製が可能です。これにより、インフラと開発プロセスを統合し、システム全体をより効率的に管理できます。 セキュリティ面の向上 DevOpsでは、開発と運用のプロセスを効率化し、自動化を促進することが重視されます。この自動化の一環として、セキュリティポリシーに基づいた自動チェックが実装されることが望ましいです。これにより、継続的にビルド・テストされたコードは、セキュリティポリシーに基づいて自動的にチェックされ、安全なソフトウェアを迅速に提供できるようになります。 DevOpsモデルの導入方法 このように、DevOpsはソフトウェア開発と運用に多くのメリットをもたらしますが、導入には、いくつかの障壁があります。 DevOps導入の障壁 DevOps導入の障壁として、以下の2つが挙げられます。 企業文化の変革の必要性 DevOpsは、開発チームと運用チームが協力してソフトウェアの開発から運用までをスムーズに行うことを目指す仕組みです。しかし従来のシステム開発方針では、開発チームと運用チームは別々に働き、それぞれに異なる目標や評価基準が存在していました。そのため、DevOpsを導入する際には、両者の役割や責任を明確にし、コミュニケーションや協調性を高めるための企業文化の変革が必要になります。 ツールの選定 DevOpsを実現するためには、適切なツールを選定することが重要です。しかし、数多くのツールが存在するため、どれを選ぶべきか判断することは容易ではありません。 DevOpsを実現するためのツール DevOpsを実現するためには、AzureやAWSなどのクラウドプラットフォーム、CI/CDツール、コンテナ管理ツールなどが必要です。 クラウドプラットフォーム クラウドプラットフォームを利用すると、インフラの設定や管理を自動化し、環境を柔軟にスケールアップ・スケールダウンできます。AzureやAWSはその代表例です。 Azure Microsoftによる提供で、Windowsとの親和性が高い点が特徴です。AIやIoTなどの先進的な技術にも対応しています。 AWS Amazonによる提供で、最も普及しているクラウドプラットフォームの一つです。サーバーレスアーキテクチャやコンテナ技術、マイクロサービスなど、最新の技術にも対応しています。 CI/CDツール CI/CDツールには、コードをビルド・テストしてリリースまでの自動化を支援する機能があり、Azure DevOpsやAWS CodePipelineが代表的なツールとして知られています。 Azure DevOps Azureクラウド上で提供されます。コードの管理からビルド、テスト、リリースまでの一連のプロセスを一元管理できます。また、GitHubやJenkinsなどの外部ツールとの連携も可能です。 AWS CodePipeline AWSクラウド上で提供されるCI/CDツールです。このサービスもビルド、テスト、リリースなどのプロセスを自動化できます。AWSの各種サービスとの連携が容易です。 コンテナ管理ツール DevOpsにおいては、コンテナ技術を活用することが多いため、コンテナ管理ツールも重要な役割を担っています。コンテナのデプロイや管理、スケーリングなどを支援する機能があります。代表的なツールとして、Azure Kubernetes ServiceやAWS Elastic Kubernetes Serviceが挙げられます。 Azure Kubernetes Service Azure上で提供されるKubernetesベースのコンテナ管理ツールで、Kubernetesクラスタの作成、管理、スケーリングを自動化できます。Azureで稼働するアプリケーションをKubernetes上で実行できるため、高い可用性や拡張性を実現できます。 AWS Elastic Kubernetes Service AWS上で提供されるKubernetesベースのコンテナ管理ツールで、コンテナの管理、スケーリング、自動復旧などを支援します。Amazon EC2上でKubernetesクラスタを構築するため、EC2の自動スケーリングやロードバランシングなど、AWSの各種サービスとの連携が容易になります。 これらのツールは、DevOpsの実践をサポートするものであり、組織やプロジェクトの要件に応じて選択・組み合わせることが可能です。また、これらのツールを効果的に活用することで、開発プロセスの自動化や効率化、コラボレーションの強化が実現できます。ただし、ツール自体がDevOpsを実現するわけではなく、適切な文化やプロセスが整備された上でツールを使うことで、DevOpsの恩恵を最大限に活用できることを理解しておくことが重要です。 Four Keysの 4つの指標 DevOpsの実践においては、プロジェクトの進捗やチームの効率化を評価する為の指標が不可欠です。そのための指標として、GoogleのDevOps Research And Assessmentチームが提唱した「Four Keys」があります。この指標を使用することで、ソフトウェア開発チームは、自分たちのパフォーマンス評価し、改善することができます。 Four Keysは、以下の4つの指標から構成されています。 デプロイ頻度 変更リードタイム 変更障害率 平均修復時間 これらの指標を定期的に測定することで、開発チームは、ソフトウェアの品質を向上させるために必要な改善点を把握できます。自身のパフォーマンスを客観的に評価し、改善することができます。 以下に、4つの指標について解説します。 デプロイ頻度 デプロイ頻度とは、開発チームが新機能や修正をリリースする頻度を示します。デプロイ頻度が高いほど、開発チームが効率的にリリースを行っていることが示されます。 変更リードタイム 変更リードタイムは、コードの変更から、本番環境でリリースされるまでの時間を示します。短い変更リードタイムは、新機能やバグ修正に迅速に対応できることを示します。 変更障害率 変更障害率とは、デプロイが原因で本番環境で障害が発生する割合を指します。変更障害率が低いことは、開発チームが信頼性の高いソフトウェアを提供できていることを示します。 平均修復時間 平均修復時間は、障害が発生してから修復するまでにかかる時間を指します。平均修復時間を短縮することで、障害を早期発見し、迅速に対応できるようになります。 Four Keyの指標は、開発チームのパフォーマンスを測定するものであり、改善に役立ちます。これらの指標を把握することで、開発チームは自身のパフォーマンスを客観的に評価し、継続的に改善を繰り返すことで、より高品質なソフトウェアを提供することができます。 まとめ 本記事では、DevOpsの基本的な概念や導入メリットについて解説しました。DevOpsは、開発チームと運用チームのコラボレーションを促進し、より効率的な開発が可能になる手法であり、今後ますます重要性が高まることが予想されます。 この記事が、エンジニアの皆さんの今後のソフトウェア開発をよりよいものにする助けになれば幸いです。 The post DevOpsとは?基本知識や導入メリットを解説 first appeared on Sqripts .
アバター
ISO/IEC/IEEE 29119は、ソフトウェアテストに関する国際標準です。この標準を理解し、適用することで、ソフトウェアの品質を向上させることが期待されます。本記事では、 ISO/IEC/IEEE 29119を学ぶ理由やメリット、デメリットについて説明します。 ISO/IEC/IEEE 29119とは? ISO/IEC/IEEE 29119は、国際標準化機構(International Organization for Standardization; ISO)によって開発されたソフトウェアテストに関する国際標準です。この標準は、いくつかの既存のテスト標準やベストプラクティスを統合し、現代のソフトウェア開発とテストのニーズに対応するように設計されています。 ISO/IEC/IEEE 29119の歴史は、2007年に始まります。ソフトウェアテストワーキンググループ(WG26)が、SC7(ISO(国際標準化機構)とIEC(国際電気標準会議)が共同で運営するJTC1(統合技術委員会1)の下で活動するサブコミッティー)の一部としてソフトウェアテスト標準を開発・維持するために2007年に設立され、新しいテスト標準の開発を開始しました。これは、以前のソフトウェアテスト標準(ISO/IEC 12207, ISO/IEC 15288, IEEE 829, IEEE 1008, BS 7925-1, BS 7925-2)が、それぞれ異なるアプローチや用語を使用しており、一貫性や適用範囲が限定的であったためです。 この新しい標準の目的は、ソフトウェアテストのプロセス、ドキュメント、技法に関する包括的で一貫性のある指針を提供することでした。その結果、 ISO/IEC/IEEE 29119は、5つのパートから構成される一連の標準として策定されました。 ISO/IEC 29119-1:2013 – ソフトウェアテストのための概念および定義 ISO/IEC 29119-2:2013 – ソフトウェアテストプロセス ISO/IEC 29119-3:2013 – ソフトウェアテストドキュメント ISO/IEC 29119-4:2015 – ソフトウェアテスト技法 ISO/IEC 29119-5:2016 – キーワード駆動型テスト 最初の4つのパートの作業が始まった直後、ISO/IEC 33063のテストプロセス評価(Part 2で定義されたテストプロセスに対する評価)が別の提案によって作成され、これに続いてISO/IEC/IEEE 29119-5のキーワード駆動型テストが開発されました。その後、WG26は、他の標準によってカバーされる動的テストを補完するために、レビューに関する別の標準(ISO/IEC 20246)を開発し、これが2017年に発行されました。 その他にも、以下に示すように、いくつかの分野で作業が進んでいます。 • 2020年発行 – AIベースのシステムのテストに関するガイドライン(ISO/IEC TR 29119-11) • 2021年発行 – アジャイルプロジェクトでのISO/IEC/IEEE 29119(すべてのパート)の使用に関するガイドライン(ISO/IEC TR 29119-6) • 進行中 – 自動車システム向けソフトウェアのテストでのISO/IEC/IEEE 29119の使用に関するガイドライン(ISO/IEC TR 29119-7) • 進行中 – モデルベースのテスト(ISO/IEC TR 29119-8) • 進行中 – ゲームテスト(ISO/IEC TR 29119-9) • 進行中 – 性能テスト(ISO/IEC 29119-10) • 進行中 – インシデント管理(ISO/IEC/IEEE xxxxx) • 進行中 – 生体認証システムのテストでのISO/IEC/IEEE 29119の使用に関するガイドライン(ISO/IEC 29119-13) • 進行中 – データ移行テスト(ISO/IEC TR 29119-14) • 進行中 – 静的解析(ISO/IEC 29119-15) • 進行中 – 大規模で複雑なシステムのテストに関するガイドライン(ISO/IEC TR 29119-16) 上記の標準番号にTRとついているものは技術報告書と呼ばれるもので、情報提供の意味合いが強く、厳密には国際規格(IS)とは異なります。また、インシデント管理の標準は、純粋にソフトウェアテストに関するものではないため、ISO/IEC 29119ソフトウェアテストシリーズの一部とは見なされず、ランダムな番号が割り当てられます。 国際規格は5年間毎に見直しがされ、必要であれば更新されます。実際、最初の4つのパートは2021年と2022年に更新されました。 • 2021年発行 – テストプロセス – 第2版(ISO/IEC/IEEE 29119-2) • 2021年発行 – テスト文書 – 第2版(ISO/IEC/IEEE 29119-3) • 2021年発行 – テスト技法 – 第2版(ISO/IEC/IEEE 29119-4) • 2022年発行 – 一般的な概念 – 第2版(ISO/IEC/IEEE 29119-1) ISO/IEC/IEEE 29119を学ぶ理由 ISO/IEC/IEEE 29119を学ぶ理由には内発的要因と外発的要因の2つあります。まずは、内発的要因ですが、主要な要因に以下の3つがあります。 a) 品質の向上 ソフトウェアテストは、品質を確保するための重要なプロセスです。 ISO/IEC/IEEE 29119は、テストプロセスの標準化を目指しており、学ぶことで品質向上につながります。 b) 信頼性の向上 ISO/IEC/IEEE 29119は、国際的な標準であり、それに従うことで、顧客やビジネスパートナーからの信頼を得ることができます。 c) 効率化 標準化されたテストプロセスは、効率的な作業ができるようになります。これにより、開発サイクルが短縮され、コスト削減にもつながります。 次に外発的要因ですが、ISO/IEC/IEEE 29119は国際規格である性格上、その準拠が求められることが挙げられます。ISO/IEC/IEEE 29119の準拠が求められる場合は、主に以下のような状況です。 a) クライアントの要求 顧客やクライアントが、ソフトウェア開発プロジェクトやテスト活動においてISO/IEC/IEEE 29119に準拠することを要求することがあります。これは、品質保証のための一般的な基準を確立し、プロジェクトのリスクを低減するためです。 b) 法規制や業界標準 特定の業界や分野では、法規制や業界標準によってISO/IEC/IEEE 29119に準拠することが求められることがあります。これは、ソフトウェアの安全性や信頼性を確保し、利害関係者に対する責任を果たすためです。 c) 国際的な取引 多国籍企業や国際的なプロジェクトでは、異なる国や地域の組織間で一貫した品質基準を確立するために、ISO/IEC/IEEE 29119に準拠することが求められることがあります。 ISO/IEC/IEEE 29119のメリット ISO/IEC/IEEE 29119を導入するメリットは多くありますが、主なものは以下の4つになります。 a) 組織全体での共通言語 ISO/IEC/IEEE 29119を導入することで、組織内でのコミュニケーションが円滑になります。共通の言語を持つことで、誤解やミスが減少し、作業効率が向上します。 b) テストプロセスの標準化 テストプロセスが標準化されることで、繰り返し実施するテストの品質が向上します。また、新しいプロジェクトに対しても、テストプロセスを迅速に適用できます。 c) ドキュメントの統一 ISO/IEC/IEEE 29119は、ドキュメントのフォーマットや内容も規定しています。これにより、ドキュメントの品質が向上し、情報の共有や管理が容易になります。 d) トレーサビリティの向上 標準化されたドキュメントやプロセスにより、テストのトレーサビリティが向上します。これにより、問題が発生した際に原因を特定しやすくなり、迅速な対応が可能となります。 ISO/IEC/IEEE 29119のデメリット ISO/IEC/IEEE 29119の導入はメリットだけではなく、考慮しなければいけないデメリットも存在します。主なものは、以下の3つです。 a) コストと時間 ISO/IEC/IEEE 29119を導入するには、初期費用や研修費用が必要です。また、標準に沿ったプロセスやドキュメントを整備するための時間も必要となります。 b) 柔軟性の低下 標準化されたプロセスやドキュメントは、柔軟性が低下する可能性があります。特定のプロジェクトに対して最適な方法が標準と異なる場合、適応が難しくなることがあります。 c) 過剰な成果物 ISO/IEC/IEEE 29119は、ドキュメントやプロセスに関して詳細な規定をしています。これが、場合によっては過剰な成果物を生む可能性があり、作業効率が低下することがあります。 まとめ ISO/IEC/IEEE 29119は、ソフトウェアテストに関する国際標準であり、品質や信頼性の向上、効率化に役立ちます。また、組織全体での共通言語やドキュメントの統一、トレーサビリティの向上などのメリットがあります。一方で、コストや時間、柔軟性の低下、過剰なフォーマリティなどのデメリットも考慮する必要があります。 学ぶ理由やメリット、デメリットを理解した上で、組織のニーズや状況に応じて ISO/IEC/IEEE 29119の導入を検討してください。適切に適用することで、ソフトウェアの品質向上や効率化に大きく貢献することができます。 The post ISO/IEC/IEEE 29119とは? 学ぶ理由、メリット、デメリットを分かりやすく解説 first appeared on Sqripts .
アバター
こんにちは!フロントエンドエンジニアのつかじです。 今回はNext.jsアプリケーションに Microsoft Clarity を導入してみたいと思います。Microsoft Clarityは、ユーザーエクスペリエンスを向上させるための無料の分析ツールです。このツールを使って、ユーザーの行動を理解し、アプリケーションのパフォーマンスを最適化しましょう。 なぜMicrosoft Clarityを導入するのか? Microsoft Clarityは、ウェブサイトのユーザーエクスペリエンスを向上させることを目的とした無料の分析ツールです。Clarityを導入する際の具体的な目的は下記の通りです。 ユーザー行動の理解 ヒートマップやセッション再生機能を利用して、ユーザーがウェブサイトでどんな行動をしているのかを知ることができます。これで、ユーザーのニーズや問題点を見つけ出し、対応策を考えることができます。 ユーザビリティの向上 セッション再生機能を利用して、ユーザーがウェブサイトで困っている場所や、ナビゲーションが難しいところを特定することができます。それらの問題を解決するための改善策を実施することでウェブサイトをもっと使いやすくできます。 コンテンツの最適化 ヒートマップ機能を利用して、ユーザーが最も興味を持っているコンテンツや、なかなかスクロールされないエリアを特定できます。これを参考に、コンテンツの配置やデザインを工夫し、ユーザーの興味を引くサイトに仕上げることができます。 コンバージョン率の向上 インサイトを利用して、コンバージョンまでのユーザーの動きを調べ、コンバージョンの障害となるポイントを見つけ出します。これを解決することで、コンバージョン率を向上させることができます。 デバイスやブラウザの最適化 インサイトダッシュボードで、ユーザーがどんなデバイスやブラウザを使っているのかを調べ、それに合わせて最適化を行います。これにより、すべてのユーザーに適したウェブサイトの提供が可能になります。 Next.jsアプリケーションへMicrosoft Clarityを導入する 1. Microsoft Clarityのアカウント作成 まずはじめに、 Microsoft Clarityのウェブサイト にアクセスし、アカウントを作成します。 アカウント作成が完了したら、プロジェクトを追加して、トラッキングコードを取得します。このトラッキングコードがNext.jsアプリケーションに必要になります。プロジェクトの追加はウェブサイト名とURLのみの入力で簡単に登録可能です。 2. Next.jsアプリケーションにトラッキングコードを追加 さて、Microsoft Clarityのトラッキングコードを手に入れたら、次はNext.jsアプリケーションに導入していきます。以下の手順で導入できます。 1. _document.tsx ファイルを作成する pages フォルダ内に _document.tsx ファイルを作成します。すでに作成済みの場合は、そのファイルを開いてください。 2.Microsoft Clarityのトラッキングコードを追加する _document.tsx ファイルの <Head> タグ内に、Microsoft Clarityのトラッキングコードを追加し、デプロイを行います。 ※ YOUR_TRACKING_CODE の部分は、実際のトラッキングコードに置き換えてください。 import Document, { Head, Html, Main, NextScript } from "next/document"; class MyDocument extends Document { render() { return ( <Html> <Head> {/* ここにトラッキングコードを追加 */} <script type="text/javascript" dangerouslySetInnerHTML={{ __html: ` (function(c,l,a,r,i,t,y){ c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); })(window, document, "clarity", "script", "YOUR_TRACKING_CODE"); `, }} /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } } export default MyDocument; 以上で導入は完了です。簡単でしたね。 Microsoft Clarityのダッシュボードでユーザー行動のデータが表示されるようになります。ヒートマップやセッション再生などの機能を使って、ユーザーの行動を分析し、アプリケーションの最適化を行いましょう。 終わりに Next.jsアプリケーションへMicrosoft Clarity導入はかなり簡単でしたね。Microsoft Clarityと統合することで、無料で分析データを取得し、ウェブサイトのユーザーエクスペリエンスを向上させることができます。これらの情報を活用して、ウェブサイトを改善し、より多くのユーザーにとって魅力的なコンテンツを提供しましょう。 The post Next.jsアプリケーションにMicrosoft Clarityを導入してユーザーエクスペリエンスを向上させよう! first appeared on Sqripts .
アバター
テスト駆動開発のスタイルを取り入れているもののテストのことはあまりよくわかっていないプログラマーと、テストへの熱い情熱をもちつつプログラマーの事情はわかっていないテスターとが、小さな障害の発見をきっかけとして出会い、役割の壁を崩しながら少しずつ協調するようになっていく、小さなお話です。 登場人物 プロ之 … プログラマー テス緒 … テスター 前回、プロ之さんとテス緒さんは協力して、問題の原因が古いIE対応サービスにあることを突き止めました。しかし、IE対応サービスはすでにサポート外でサービスも停止済みであることがわかりました。プロ之さんは停止済みサービスが今後問題を起こすはずがないと結論し、テス緒さんは原因追及が振り出しに戻ってしまい途方に暮れています。 問題はどこにいった? プロ之さんはIE対応サービスが1年以上前に終了していると聞き、自分の目でもゲートウェイが存在せずクラスター内にも稼働していないことを確認しました。テス緒さんと調べていた問題がIE対応サービスに存在していたとしても、実行されなければ今後問題になるはずがありません。修正する意味もありません。 「(完全に時間の無駄だっただろうか?)」プロ之さんは考えてみました。「(そんなことはない)」とプロ之さんは自分で答えました。調査を通じて新しく学んだことは多く、テストの考え方や観点も参考になるし、今後テストチームとコミュニケーションするときもスムーズにできそうです。「(一定の満足が得られた、有意義な活動だった)」そう結論しながら、イシュー管理システムにテス緒さんが数週間前に作ったチケットを、開発チームの担当者として「対応なし」でクローズしようとしました。 その寸前に、テス緒さんからチャットのメッセージが届きました。「ちょっと相談できる?」 プロ之さんはメッセージで返信しました。「いまチケットをクローズするところです。どんな相談ですか?」 テス緒(以下、T)「問題の他の原因について」 プロ之(以下、P)「原因は判明しました。発生した現象と完全に一致しています。他の可能性は考えられません。今後実行しないコードなのでこれ以上問題は起きません。これ以上の調査と対応は優先順位を下げるべきです」 T「そうだよね、でもおかしい気がして。話せない」 P「これまでの調査や議論は無駄ではなかったと考えています。テス緒さんにもいろいろ教えていただきましたし、有意義でした。ですが今回の問題はクローズです。いまクローズするところです。そうしないとチームリーダーにも文句を言われます」 突然背後で呼び出し音が鳴り、プロ之さんは飛び上がりました。鳴ったのは社用携帯電話で、開発チームの緊急連絡用なのでめったに使いません。プロ之さんは用心して、通話をスピーカーフォンモードにしました。 携帯電話からはテス緒さんのあわてた声が聞こえてきました。「ああよかった、番号間違えたかと思った。どうしても話をしたくって。あ、すみません、番号間違ってないですよね? プロ之さんだよね?」 P「そうです」 T「よかった! もうこれからどうしたらいいかわかんなくなっちゃって、リーダーにも次の作業をせっつかれるし、相談に乗ってもらえないし、プロ之さんもう話してくれないし、調べても無駄とか話しても有意義じゃないとか冷たいし」 P「そんなことは言ってません。ですが現時点ではやるべきことをやりました。これ以上は優先順位を下げるべきです。問題のコードが書かれたのはずいぶん前なので十分な調査ができる気はしません。1年以上動作していませんし…」 「1年前!」テス緒さんの大声で携帯電話が震えました。「ちょっと待ってちょっと見て日付」 プロ之さんからのチャットで大量のログが送られてきました。大量すぎて内容は把握できませんが、日付の部分を眺めると1ヶ月か2ヶ月前のものになっています。 T「見て! IE対応サービスが1年以上動いてないのに、このログは1ヶ月前なんだよ! データがおかしくなっているところも、最近1年以内にあったはず。だからきっとほかに原因があるはずで…プロ之さん? 聞いてる?」 プロ之さんは考え込んでいて、聞こえていませんでした。「(あのコードは1年以上動いていない。このログを出すのはあのコードしかあり得ない。このログは1ヶ月前に、本番環境で出ている。ということは)」 「あのコードがどこかで動いている」プロ之さんは声に出して言いました。 テス緒さんは聞き返します。「でもIE対応のサービスは動いていないんでしょう?」 「動いていないはずです。それが理論的推論です。ですが動いています。これは観測した事実です。推論と事実では、必ず事実が勝ちます。コードは動いています」プロ之さんは断言しました。 2人のヒートアップしたやり取りから、新たな可能性が見えてきました。プロ之さんは調査結果から自分の結論を出しました。テス緒さんは、うまく言葉にできないもやもやを抱えながら、プロ之さんのヒントに新たな糸口を見出しました。 ここでは、プロ之さんが冷静な判断を見せています。調査結果自体は事実ですが、そこから論理的に出した結論は推論です。推論は強力な武器ですが、もしそれに反する証拠や事実が新たに見つかったら、間違っているのは推論のほうです。見つかった事実に合わせて、論理を組み立て直すことになります。 そして2人がヒートアップしながらも、相手を非難したり、萎縮させたりはしていない点にも注目できます。同じことを同じように言っても、相手によっては攻撃を受けたように感じたり、守りに入ったりして、率直な議論ができなくなる場合があります。この2人がこれまで積み重ねてきた関係性とお互いへの信頼があるからこそ、第三者から見たら激しく見えるようなやりとりでも建設的になります。2人それぞれの性格も、関係あるかもしれません。 ポイント: 観測した事実と論理で導かれる可能性を統合して問題を絞り込む 信頼関係を積み重ねているからこそ率直な議論ができる それは人の問題で、チームの問題 ここからは後日談になります。プロ之さんはログを出力しているインスタンスを見つけ、インスタンスの内部を調査して、本来は存在しないはずの該当コードがデプロイされているのを確認しました。さらにインスタンス固有のAPI設定を手で書き換えた形跡があり、そのせいで呼び出されないはずのIE対応サービスのコードが実行されていたことがわかりました。その特定のインスタンスでのみ発生する現象だったため、これまで見落とされてきたのです。 この発見は開発チームと運用チーム両方で重大な問題として調査することになりました。その結果、2年前に大規模なリリースをしたとき、開発者が動作確認をするため一時的にIE対応サービスのコードをデプロイし、APIの設定も書き換えていたのですが、それを元に戻し忘れていたことがわかりました。作業ミスをしたのは、なんと今の開発チームリーダーだったとのことです。 対応としてAPI設定を正しく直したのはもちろんですが、このような作業ミスが起きたこと、それを今まで見逃してきたことも問題視され、対策が検討されました。開発リーダーのような優秀な人でもミスをするのだから、本番環境を直接操作するような運用は危ないと再認識され、リリース作業の自動化が前進しました。また不要なコードのデプロイ防止策として、リリースノートをテストチームと共同で書くという案を検討しています。 テストチームでもテスト観点を見直しました。ソフトウェアを動かして確認するだけでは見落としが発生するという認識から、デプロイプロセスの確認や、設定内容の確認などもテストに含めることにしたのです。こうした確認の一部は開発チームの力を借りて自動化されました。テス緒さんが「同じ内容のテストを手で繰り返すなら自動化すべき」と主張したのが採用されたそうです。 ポイント: ソフトウェアの問題は、誰かが「やらかした」結果なので、人の問題と言える 起きた問題ではなくその原因を直しに行く。問題が起きないように直す 問題を解決した!さてお次は? いろいろな変化が起きていく中で、プロ之さんとテス緒さんは久しぶりにリアルで顔を合わせました。 T「やー、なんだか大変なことになっちゃったね。手順も変わるしツールも新しくなるし。よく、お前のせいだからな! ってリーダーに言われるんだよ。笑いながらだけど」 P「私たちのせいではありません。タイミング良く見つけただけです。開発リーダーも少し静かになっていましたが、今は新しいことに取り組むのに忙しそうです」 T「開発リーダーさんは新しいこと好きそうだよね。でもこれが落ち着いたら、いろいろ良くなりそう。テストチームでもテスト自動化を勉強してるんだよ」 P「開発プロセスが現代的になりそうですし、DevOpsの考え方も進んでいます。良くなりそうですね」 テストで見つかった問題をきっかけとして、各チームが対策を取り、チーム間の協力も強化されそうです。失敗から学べる、優秀な組織のようです。人為的ミスを減らす工夫は、品質にも良い影響がありますし、作業の効率化にもつながります。問題への見事な対応だと言えます。 G.M.ワインバーグの著書『コンサルタントの秘密』(1990, 共立出版)に、こんな言葉が紹介されています。 第一番の問題を取り除くと、第二番が昇進する 一番の問題、いま最も重要な問題、まず解決すべき問題を無事に解決できたら、それは素晴らしいことです。しかし同時に、それまで二番手だった問題がトップに躍り出てきます。問題に対処しても問題はなくならない、また次の問題が現れるだけであるという法則です。[ 1 ] T「ところでね、昨日こんな不思議な現象があったんだけど…」 P「テストチームのテスト自動化で、気になることが…」 2人もまた新たな問題を見つけたようです。問題は途切れないかもしれませんがひとつずつ片付ければ、ひとつずつ状況を良くしていけます。小さな問題でも大きな問題でも、根本的な原因をたどって改善のきっかけにできます。こんどの問題は簡単なものでしょうか、チームやプロダクト全体を巻き込むようなものでしょうか、はたまた…? ポイント: 問題を解決しても問題はなくならない。次の問題が登場する チームの品質とプロダクトの品質を両方とも改善していく 本連載は今回が最終回となります。最後まで読んでいただき、ありがとうございます。 [1] 書籍ではワインバーグが13歳の時、スーパーでアルバイトをした話が紹介されています。そこで、野菜売場でルタバガ(カブに似た野菜)の売れ行きがとても悪いことに気づきました。野菜売場責任者のルウディーが売場スペースを整理しようとして、ワインバーグになにかアイデアがないか聞きました。ルタバガを減らすのはどうかとワインバーグが答え、ルウディーはその案を喜んで採用します。ルウディーはルタバガを片付けてから、こうワインバーグに聞きました。 「で、ルタバガの次は何だね」 問題をひとつ片付ければ、次の問題が登場します。おまけにそれも片付けるよう期待されてしまうかもしれません。これが「ルウディーのルタバガの法則」です。 第4回:立場を越えて問題を追及しよう 第3回:大事(だいじ)なことが本当に大事か確かめよう 第2回:それぞれの得意をつなぎ合わせよう 第1回:引っかかりを感じたら相談しよう The post 【テスターと開発者が上手に協力するには】第5回:テストを通じてチームとプロダクトとに貢献しよう first appeared on Sqripts .
アバター
こんにちは!フロントエンドエンジニアのつかじです。 皆さんはREST APIクライアントをどのように開発していますか?私はAPIクライアントを手作業で作成するのは手間がかかるため、普段のプロダクト開発ではOpenAPI Generatorを使って自動生成しています。しかし先日、Microsoftが新しいAPIクライアント生成ツール「Kiota」を 発表 しました。気になった方も多いのではないでしょうか? 今回は、Microsoftから新しく発表されたAPIクライアント生成ツール「Kiota」を使って、Node.js(TypeScript)のプロジェクトでAPIクライアントを生成し、実際に動かしてみたいと思います。 1. Kiotaのインストール こちら の公式ドキュメントを参照してインストールします。 ※ 私は.NET toolでインストールしました 2. Node.js(Typescript)サンプルプロジェクト作成 npm init npm install -D typescript ts-node npx tsc --init 3. Kiotaの依存パッケージをインストール Kiotaが生成したAPIクライアントのビルド、実行のために抽象化パッケージへの参照が必要です。 npm install @microsoft/kiota-abstractions npm install @microsoft/kiota-http-fetchlibrary npm install @microsoft/kiota-serialization-form npm install @microsoft/kiota-serialization-json npm install @microsoft/kiota-serialization-text 4. KiotaでAPIクライアントを生成 今回は Swagger PetStore からAPIクライアントを生成したいと思います。 Swagger PetStoreは、Swagger(現在のOpenAPI)のサンプルAPIで、ペットストアの基本的な操作を提供しています。Swagger PetStoreは、APIの定義、実装、ドキュメント化のデモンストレーションを目的として設計されており、試すことができます。 Kiota CLIにて下記のコマンドを実行 kiota generate -l typescript -d <https://petstore.swagger.io/v2/swagger.json> -c PetStoreClient -o ./petstore-client すると、 petstore-client ディレクトリ以下に下記のAPIクライアントのコードが無事に生成されました! . ├── kiota-lock.json ├── models │ ├── apiResponse.ts │ ├── category.ts │ ├── createApiResponseFromDiscriminatorValue.ts │ ├── createCategoryFromDiscriminatorValue.ts │ ├── createOrderFromDiscriminatorValue.ts │ ├── createPetFromDiscriminatorValue.ts │ ├── createTagFromDiscriminatorValue.ts │ ├── createUserFromDiscriminatorValue.ts │ ├── index.ts │ ├── order.ts │ ├── order_status.ts │ ├── pet.ts │ ├── pet_status.ts │ ├── tag.ts │ └── user.ts ├── pet │ ├── findByStatus │ │ ├── findByStatusRequestBuilder.ts │ │ ├── findByStatusRequestBuilderGetQueryParameters.ts │ │ └── findByStatusRequestBuilderGetRequestConfiguration.ts │ ├── findByTags │ │ ├── findByTagsRequestBuilder.ts │ │ ├── findByTagsRequestBuilderGetQueryParameters.ts │ │ └── findByTagsRequestBuilderGetRequestConfiguration.ts │ ├── item │ │ ├── createWithPetPostRequestBodyFromDiscriminatorValue.ts │ │ ├── index.ts │ │ ├── uploadImage │ │ │ ├── uploadImageRequestBuilder.ts │ │ │ └── uploadImageRequestBuilderPostRequestConfiguration.ts │ │ ├── withPetItemRequestBuilder.ts │ │ ├── withPetItemRequestBuilderDeleteRequestConfiguration.ts │ │ ├── withPetItemRequestBuilderGetRequestConfiguration.ts │ │ ├── withPetItemRequestBuilderPostRequestConfiguration.ts │ │ └── withPetPostRequestBody.ts │ ├── petRequestBuilder.ts │ ├── petRequestBuilderPostRequestConfiguration.ts │ └── petRequestBuilderPutRequestConfiguration.ts ├── petStoreClient.ts ├── store │ ├── inventory │ │ ├── createInventoryResponseFromDiscriminatorValue.ts │ │ ├── index.ts │ │ ├── inventoryRequestBuilder.ts │ │ ├── inventoryRequestBuilderGetRequestConfiguration.ts │ │ └── inventoryResponse.ts │ ├── order │ │ ├── item │ │ │ ├── withOrderItemRequestBuilder.ts │ │ │ ├── withOrderItemRequestBuilderDeleteRequestConfiguration.ts │ │ │ └── withOrderItemRequestBuilderGetRequestConfiguration.ts │ │ ├── orderRequestBuilder.ts │ │ └── orderRequestBuilderPostRequestConfiguration.ts │ └── storeRequestBuilder.ts └── user ├── createWithArray │ ├── createWithArrayRequestBuilder.ts │ └── createWithArrayRequestBuilderPostRequestConfiguration.ts ├── createWithList │ ├── createWithListRequestBuilder.ts │ └── createWithListRequestBuilderPostRequestConfiguration.ts ├── item │ ├── withUsernameItemRequestBuilder.ts │ ├── withUsernameItemRequestBuilderDeleteRequestConfiguration.ts │ ├── withUsernameItemRequestBuilderGetRequestConfiguration.ts │ └── withUsernameItemRequestBuilderPutRequestConfiguration.ts ├── login │ ├── loginRequestBuilder.ts │ ├── loginRequestBuilderGetQueryParameters.ts │ └── loginRequestBuilderGetRequestConfiguration.ts ├── logout │ ├── logoutRequestBuilder.ts │ └── logoutRequestBuilderGetRequestConfiguration.ts ├── userRequestBuilder.ts └── userRequestBuilderPostRequestConfiguration.ts 5. Kiotaで生成されたAPIクライアントでAPIを叩く 次に、生成されたAPIクライアントを使って、実際にSwagger PetStore APIにアクセスしてみましょう。 以下のサンプルコードを** index.ts **というファイル名でプロジェクトディレクトリに作成し、 import { AnonymousAuthenticationProvider } from "@microsoft/kiota-abstractions"; import { FetchRequestAdapter } from "@microsoft/kiota-http-fetchlibrary"; import { PetStoreClient } from "./petstore-client/petStoreClient"; (async () => { const authProvider = new AnonymousAuthenticationProvider(); const adapter = new FetchRequestAdapter(authProvider); const client = new PetStoreClient(adapter); const pet = await client.petById("1").get(); console.log(pet); })(); 実行すると、コンソールログにレスポンスの内容が表示されます。これでSwagger PetStore APIとのやりとりができるようになりました! おわりに 今回は、Microsoftから発表されたばかりのKiotaを使って、TypeScriptのAPIクライアントを簡単に生成することができました。Kiotaは新しいプロジェクトであり、まだ発展途上ですが、今後の機能追加や言語サポートにも期待大ですね!みなさんもぜひ試してみてください! The post Microsoftの新しいAPIクライアント生成ツールKiotaを試してみた first appeared on Sqripts .
アバター
テスト自動化のお仕事をしているきむらです。 Windowsアプリの自動操作に興味があるけど、自動化ツールが色々あってよくわからない。 自動化ツールのセットアップとか難しそう。。 そんな、自動化の世界に飛び込めずにいる方のために、自動化ツールをインストールしないで、Windowsに標準搭載されている「UI オートメーション」機能を使って、アプリを自動操作する方法を紹介したいと思います。 用意したPowerShellのスクリプトをコピペして実行するだけで体験できますので、気楽な感じでお付き合いいただければと思います。 環境 この記事のPowerShellスクリプトは下記の環境で動作確認しています。 Microsoft Windows 10 Pro 22H2 PowerShell 5.1.19041.2673 Microsoft Windows 11 Pro 22H2 PowerShell 5.1.22621.963 Microsoft Edge 112.0.1722.58 UIオートメーションとは 「UIオートメーション」は、ざっくり言うと「ユーザーインターフェイスをプログラムから操作したりすることができる」機能で、Windowsに標準搭載されています。 もっと詳しく知りたい方は「 UI オートメーションの概要 」をご参照ください。 Windows PowerShell ISEを起動する 「Windows PowerShell ISE」はWindowsに標準搭載されているPowerShellの統合開発環境で、PowerShellスクリプトを効率的に作成することができるアプリです。 タスクバーの検索ボックスに「powershell」を入力して、検索結果から「Windows PowerShell ISE」を選択して起動します。起動したら、ツールバーの「スクリプトを新規作成します」ボタンを選択します。(またはメニューバーから [ファイル] > [新規作成] を選択します。) 上半分の背景が白色のウィンドウが「スクリプトウィンドウ」で、こちらにスクリプトをコピペしていきます。 下半分の背景が紺色のウィンドウは「コンソールウィンドウ」で、コマンドを入力・実行したりするウィンドウです。 UIを自動操作するための土台となるスクリプトコピペする まずは、UIを自動操作するための土台となるスクリプトをコピペします。 このスクリプトには、要素をクリックしたり、キーボード操作をする関数(部品のようなもの)が書かれていて、この関数を使って自動操作をおこないます。 下記のスクリプトをコピーします。 # Windows PowerShellでアプリを自動操作するスクリプト # UI オートメーションを使うための準備 Add-Type -AssemblyName "UIAutomationClient" Add-Type -AssemblyName "UIAutomationTypes" $AutomationElement = [System.Windows.Automation.AutomationElement] $TreeScope = [System.Windows.Automation.TreeScope] $Condition = [System.Windows.Automation.Condition] $InvokePattern = [System.Windows.Automation.InvokePattern] $SendKeys = [System.Windows.Forms.SendKeys] $Cursor = [System.Windows.Forms.Cursor] # マウスの左クリック操作をおこなうための準備 $SendInputSource =@" using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; public class MouseClick { [StructLayout(LayoutKind.Sequential)] struct MOUSEINPUT { public int dx; public int dy; public int mouseData; public int dwFlags; public int time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] struct INPUT { public int type; public MOUSEINPUT mi; } [System.Runtime.InteropServices.DllImport("user32.dll")] extern static uint SendInput(uint cInputs, INPUT[] pInputs, int cbSize); public static void Click() { INPUT[] input = new INPUT[2]; input[0].mi.dwFlags = 0x0002; input[1].mi.dwFlags = 0x0004; SendInput(2, input, Marshal.SizeOf(input[0])); } } "@ Add-Type -TypeDefinition $SendInputSource -ReferencedAssemblies System.Windows.Forms, System.Drawing $MouseClick = [MouseClick] # 要素を取得する関数 function GetElements { Param($RootWindowName = $null) if ($RootWindowName -eq $null) { try { return $AutomationElement::RootElement.FindAll($TreeScope::Subtree, $Condition::TrueCondition) } catch { return $null } } else { $childrenElements = $AutomationElement::RootElement.FindAll($TreeScope::Children, $Condition::TrueCondition) foreach ($element in $childrenElements) { if ($element.GetCurrentPropertyValue($AutomationElement::NameProperty) -eq $RootWindowName) { return $element.FindAll($TreeScope::Subtree, $Condition::TrueCondition) } } Write-Host "指定された名前 '${RootWindowName}' のウィンドウが見つかりません。" } return $null } # 要素を検索する関数 function FindElement { Param($RootWindowName = $null, $PropertyType, $Identifier, $Timeout) $startTime = (Get-Date).Ticks do { foreach ($element in GetElements -RootWindowName $RootWindowName) { try { if ($element.GetCurrentPropertyValue($AutomationElement::$PropertyType) -eq $Identifier) { return $element } } catch { continue } } } while (((Get-Date).Ticks - $startTime) -le ($Timeout * 10000)) throw "指定された要素 '${Identifier}' が見つかりません。" } # クリック操作をおこなう関数 function ClickElement { Param($RootWindowName = $null, $PropertyType, $Identifier, $Timeout = 5000) $startTime = (Get-Date).Ticks do { $element = FindElement -RootWindowName $RootWindowName -PropertyType $PropertyType -Identifier $Identifier -Timeout $Timeout $isEnabled = $element.GetCurrentPropertyValue($AutomationElement::IsEnabledProperty) if ($isEnabled -eq "True") { break } } while (((Get-Date).Ticks - $startTime) -le ($Timeout * 10000)) if ($isEnabled -ne "True") { throw "指定された要素 '${Identifier}' が有効状態になりません。" } if ($element.GetCurrentPropertyValue($AutomationElement::IsInvokePatternAvailableProperty) -eq "True") { $element.GetCurrentPattern($InvokePattern::Pattern).Invoke() } else { # IsInvokePatternAvailablePropertyがFalseの時はマウスカーソルを要素に移動して左クリックする $clickablePoint = $element.GetClickablePoint() $Cursor::Position = New-Object System.Drawing.Point($clickablePoint.X, $clickablePoint.Y) $MouseClick::Click() } } # キーボード操作をおこなう関数 function SendKeys { Param($RootWindowName = $null, $PropertyType, $Idendifier = $null, $Keys, $Timeout = 5000) if ($Idendifier -ne $null) { $element = FindElement -RootWindowName $RootWindowName -PropertyType $PropertyType -Identifier $Idendifier -Timeout $Timeout $element.SetFocus() } $SendKeys::SendWait($Keys) } # Microsoft EdgeでWebキャプチャの保存操作をおこなう関数 function SaveWebCaptureByMicrosoftEdge { SendKeys -Keys "^(+S)" ClickElement -PropertyType "AutomationIdProperty" -Identifier "view_52561" ClickElement -PropertyType "AutomationIdProperty" -Identifier "save_button_id" Start-Sleep -Seconds 3 SendKeys -Keys "{ESCAPE}" } # ↓↓↓↓↓ この行以降にアプリを自動操作するスクリプトを書く ↓↓↓↓↓ 次に「Windows PowerShell ISE」のスクリプトウィンドウに貼り付けます。 「ここで一度ファイルに保存しておこうかな」となるかもしれませんが、 ここでは保存しないでください。 ファイルに保存すると、PowerShellの実行ポリシーの設定によってはスクリプトが実行できなくなるためです。 PowerShellの実行ポリシーについてはあとで説明します。 電卓を自動操作するスクリプトをコピペして実行する では、Windowsアプリの自動操作の練習台として定番(?)の電卓を自動操作してみましょう。 「電卓を起動して、1から10までを足し算する操作」を自動操作してみます。 下記のスクリプトをコピーします。 ################################################################################ # 電卓を自動操作する ################################################################################ # 足し算する値の範囲を設定する $start = 1 $end = 10 # ボタンをクリックした後の待機ミリ秒を設定する $waitMilliseconds = 300 # 電卓アプリを開始する Start-Process calc -Wait # 電卓アプリを操作する foreach ($count in $start..$end) { # 数値を1桁ずつに分割する $array = $count.ToString().ToCharArray() # 電卓アプリの数値ボタンをクリックする foreach ($number in $array) { ClickElement -RootWindowName "電卓" -PropertyType "AutomationIdProperty" -Identifier "num${number}Button" Start-Sleep -Milliseconds $waitMilliseconds } # 現在のカウントで処理を分岐する if ($count -ne $end) { # 範囲の終わり以外の時は[+]ボタンをクリックする ClickElement -RootWindowName "電卓" -PropertyType "AutomationIdProperty" -Identifier "plusButton" Start-Sleep -Milliseconds $waitMilliseconds } else { # 範囲の終わりの時は[=]ボタンをクリックする ClickElement -RootWindowName "電卓" -PropertyType "AutomationIdProperty" -Identifier "equalButton" Start-Sleep -Milliseconds $waitMilliseconds } } 次に、スクリプトウィンドウの「141行目」に貼り付けます。 これで準備ができました。 では、ツールバーの緑色の「 ︎」(スクリプトを実行)ボタンを選択して、スクリプトを実行してみましょう。 電卓が起動して、1から10までを足し算する操作がおこなわれて、計算結果に55が表示されます。 操作間隔を空けずに自動操作する 実行したスクリプトは、自動操作の様子を確認しやすいように操作の間隔を空けています。 自動操作の間隔を空けずに実行するとどうなるか見てみましょう。 「1から10までの足し算」はあっと言う間に終わってしまいますので、ついでに足し算する範囲を「1から100まで」に変更してみましょう。 まず、スクリプトの147行目の「 $end = 10  」を「 $end = 100 」に編集します。 145 # 足し算する値の範囲を設定する 146 $start = 1 147 $end = 100 次に、スクリプトの150行目の「 $waitMilliseconds = 300 」を「 $waitMilliseconds = 0 」に編集します。 149 # ボタンをクリックした後の待機ミリ秒を設定する 150 $waitMilliseconds = 0 ツールバーの緑色の「 ︎」(スクリプトを実行)ボタンを選択して、スクリプトを実行してみましょう。なお、スクリプトの実行を途中で停止したい時は、ツールバーの赤色の「■」(操作の停止)ボタンを選択します。電卓が起動して、1から100までを足し算する操作が爆速でおこなわれて、計算結果に5050が表示されます。筆者の環境では、自動操作の間隔を空けた時の実行所要時間は「およそ1分50秒」で、間隔を開けない時の実行所要時間は「およそ15秒」でした。 Microsoft Edgeを自動操作するスクリプトをコピペして実行する 続いて、ブラウザを自動操作するスクリプトを紹介します。 ブラウザの自動操作は「Selenium」や「Autify」、「mabl」などの自動化ツールを使う方が多いかもしれませんが、ちょっとした操作であれば「UI オートメーション」でも自動操作することができます。 今回は「Microsoft Edgeを起動して、Bingのトップページを開いたあとに、検索とWebキャプチャを保存する操作をおこない、最後にダウンロードフォルダーを開く」操作を自動操作してみます。 「Microsoft Edge」を初めて使う場合は、初回実行時の設定が必要になりますので、一度「Microsoft Edge」を起動して初回実行時の設定を完了させておいてください。 また、アドレスバーに「edge://settings/downloads」を入力しEnterキーを押下して表示されるダウンロードの設定項目「ダウンロード時の動作を毎回確認する」が既定値の「オフ」になっていることを前提として自動操作しますので、設定を「オン」にしている場合は「オフ」に設定してください。 まず、電卓を自動操作するスクリプト(141行目から最後の行まで)を削除します。 次に、下記のスクリプトをコピーします。 ################################################################################ # Microsoft Edgeを自動操作する ################################################################################ # 検索する値を設定する $searchWords = @( 'フェンダー' 'ギブソン' 'ポール・リード・スミス' ) # ページ読み込み完了待ち秒数を設定する $pageLoadWaitSeconds = 3 # Microsoft Edgeを開始する Start-Process msedge -Wait # Microsoft Bingのトップページを開く SendKeys -PropertyType "AutomationIdProperty" -Idendifier "view_1020" -Keys "https://www.bing.com/{ENTER}" Start-Sleep -Seconds $pageLoadWaitSeconds # 「$searchWords」に記載されている値を検索してWebキャプチャを保存する $index = 0 foreach ($word in $searchWords) { # 2回目以降の検索時は検索ボックスの内容をクリアする if ($index -gt 0) { ClickElement -PropertyType "AutomationIdProperty" -Identifier "sb_form_q" ClickElement -PropertyType "AutomationIdProperty" -Identifier "sw_clx" Start-Sleep -Seconds 1 } # 検索ボックスに値を入力して検索する SendKeys -PropertyType "AutomationIdProperty" -Identifier "sb_form_q" -Keys "${word}{ENTER}" Start-Sleep -Seconds $pageLoadWaitSeconds # 1回目の検索時は画像リンクをクリックする if ($index -eq 0) { ClickElement -PropertyType "NameProperty" -Identifier "さらに表示" ClickElement -PropertyType "NameProperty" -Identifier "画像" Start-Sleep -Seconds $pageLoadWaitSeconds } # Webキャプチャを保存する SaveWebCaptureByMicrosoftEdge $index += 1 } # エクスプローラーでダウンロードフォルダーを開く explorer.exe $env:USERPROFILE\Downloads スクリプトウィンドウの「141行目」に貼り付けます。 なお、 145 # 検索する値を設定する 146 $searchWords = @( 147 'フェンダー' 148 'ギブソン' 149 'ポール・リード・スミス' 150 ) の「フェンダー」とかの文字列は、とりあえず適当に書いただけですので、他の文字列に編集してもよいです。 では、ツールバーの緑色の「 ︎」(スクリプトを実行)ボタンを選択して、スクリプトを実行しましょう。 Microsoft Edgeが起動してBingのトップページを開いたあとに、検索とWebキャプチャを保存する操作が繰り返しおこなわれ、最後にダウンロードフォルダーが開きます。 ※ うまく動かない時は、ツールバーの赤色の「■」(操作の停止)ボタンを選択してスクリプトを停止してください。 PowerShellの実行ポリシー 「 UIを自動操作するための土台となるスクリプトコピペする 」で、 ひとまずファイルに保存したくなるかもしれませんが、ここでは保存しないでください。 ファイルに保存すると、PowerShellの実行ポリシーの設定によってはスクリプトが実行できなくなるためです。 PowerShellの実行ポリシーについてはあとで説明します。 と書きましたが、ここでファイル保存した状態でスクリプトを実行してみましょう。 「Windows PowerShell ISE」ウィンドウのツールバーのフロッピーディスクアイコンのボタン(スクリプトを保存します)を選択します。(またはメニューバーから [ファイル] > [名前を付けて保存] を選択します。) 「名前を付けて保存」ダイアログが表示されたら、任意の場所・ファイル名で保存します。 では、ツールバーの緑色の「 ︎」(スクリプトを実行)ボタンを選択して、スクリプトを実行しましょう。 お使いの環境によりますが、PowerShellの実行ポリシーが「スクリプトの実行が許可されていない」ポリシーに設定されている場合は、悪意のあるスクリプトの実行を防止するための安全機能が働き「セキュリティ エラー」が発生して、スクリプトの実行が中断されます。 そこで今回は「今現在使用しているWindows PowerShell ISEのみスクリプトの実行を許可」してみます。 まず、コンソールウィンドウに下記を入力して実行します。 Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process すると、異様に横長なダイアログが表示されるので [すべて続行] を選択します。 これでファイル保存したスクリプトが実行できるようになりましたので、試しにもう一度ツールバーの緑色の「 ︎」(スクリプトを実行)ボタンを選択して、スクリプトを実行してみましょう。 今度は「セキュリティ エラー」が発生せずにスクリプトが実行されます。 今回は「今現在使用しているWindows PowerShell ISEのみスクリプトの実行を許可」しましたが、他に「現在のユーザーにスクリプトの実行を許可(-Scope CurrentUser)」したりすることができます。 もっと詳しく知りたい方は「 about_Execution_Policies 」をご参照ください。 さいごに 今回は自動化ツールをインストールしないで、Windowsに標準搭載されている「UI オートメーション」機能を使ってアプリを自動操作する方法を紹介しました。 ブラウザの自動操作は「 Microsoft Edgeを自動操作するスクリプトをコピペして実行する 」で書いたように各種自動化ツールを使う方が多いかもしれませんが、簡単な内容であれば今回体験したように、自動化ツールをインストールしなくても自動操作することができます。 これを機に、自動化に取り組んでみてはいかがでしょうか。 また「自動化ツールをインストールすることができない環境で自動化したい」という状況の時にも対応することができるようになりますので、頭の片隅に残しておいていただけると、いつか役に立つ時がくるかもしれません。 それではまた機会があれば。 The post UIオートメーション〜コピペで体験Windowsアプリの自動操作 first appeared on Sqripts .
アバター
はじめに みなさんは、「ブロックチェーン」という言葉を聞いたことがあるでしょうか? ブロックチェーンとは、ビットコインやイーサリアムなどの「暗号資産」と呼ばれるデジタルな通貨や資産を実現するために使われている技術です。 暗号資産は、銀行の預金や企業発行の電子マネーなどとは異なり、暗号技術を用いて誰でも自由に通貨を発行できる点に特徴があります。暗号資産技術により、2023年4月現在までに、少なくとも9000種類(※1)を超える暗号資産が発行され、暗号資産取引所などで取引が行われています。 ブロックチェーンの技術的な特徴として、暗号資産などの取引データがすべて公開され、誰でもデータを閲覧したり、取引が正当なものかを検証したりできる点があります。例えば、2009年から稼働しているビットコインのブロックチェーンでは、稼働当時から現在までの「どのアカウントがどれくらいのビットコイン残高を持っているか」「過去どんな取引をしたか」といった情報を誰でも自由に閲覧できます(図1)。 図1. Blockchain.com で閲覧できるビットコインの取引データ例 こうしたブロックチェーン上のデータは【オンチェーンデータ】とも呼ばれ、パブリックなビッグデータとしての活用が検討されています。 ブロックチェーンの応用例は、暗号資産のような通貨や資産の送付や売買だけでなく、土地や建物などの物理的な資産と紐づく【デジタル資産】や、それらを対象とした【金融商品】、データの永続性を利用した【証明書サービス】、ゲーム内アイテムやコインを現実の資産として扱える【ブロックチェーンゲーム】など、さまざな分野やアプリケーションに広がりを見せています。 それとともに、オンチェーンデータとして利用できる情報源や活用の幅も広がってきています。 本連載では、ブロックチェーンの基本的な仕組みを解説しながら、オンチェーンデータを分析するための基本的な手法について、全8回で紹介します。 分析のためのツールとして、データべースやビッグデータのデータ処理のために広く使われている【SQL】と呼ばれるクエリ言語を利用します。これまでSQLを使ったことがない人も対象にして、初歩的な構文から実践的なテクニックまでを幅広く紹介していく予定です。 ブロックチェーンのオンチェーンデータ分析に興味がある人はもちろん、これからブロックチェーンを学びたい人や、SQLのスキルを身につけたい人にとっても役立つ情報を発信していきますので、ぜひご活用いただければ幸いです。 ※1 CoinMarketCap ブロックチェーンとは 本連載の第1回目では、ブロックチェーンの歴史について概観し、代表的なブロックチェーンの違いや関係性について紹介します。 ビットコインの誕生 2008年11月、サトシ・ナカモトを名乗る人物がビットコインと呼ばれる新しい電子通貨に関する論文を発表しました。翌2009年1月にはビットコインのソフトウェアが公開され、運用が開始されます。このビットコインを実現するために発明された中核技術が、のちにブロックチェーンと呼ばれています。 このとき投稿された論文(図2)は、PDFで9ページ程度の短い文章であり、現在 bitcoin.org にて各言語に翻訳されて公開されているため、興味のある方はぜひ読んでみてください。 図2. Bitcoin: A Peer-to-Peer Electronic Cash System ビットコインの技術的な解説は本連載の第2回目以降の記事に譲るとして、今回はその社会的受容の歴史について紹介します。 ビットコイン受容の歴史 ビットコインの論文は、サトシ・ナカモトによって暗号理論に関するメーリングリスト(※2)に投稿されましたが、メーリングリストのメンバーからは懐疑的な反応が寄せられました。ビットコインのアイデアは、単に数学的なアプローチで証明できるものではなく、「ビットコインの運用に関わる実際のユーザーたちがどのように行動するか」といった経済学的な側面や、「世界規模の自律的分散システムが正常に動作し続けられるか」といったコンピュータサイエンス的な側面が複雑に絡み合っており、想像だけで理解することが難しいものだったためです。 そこで、サトシ・ナカモトは、実際に動作するシステムのコードを作成し、アイデアに賛同してくれたメンバー間でそのシステムを動かしてみることにしました。いくつかのバグ修正のあと、そのシステムは動作を開始し、約10分に1回のペースで、新しいビットコインが「採掘」され、メンバーの間で送金しあえる新しい電子通貨が誕生しました。 当初、この新しい電子通貨には全く価値が付いていない単なる電子データでした。そこで、ビットコインのアイデアに賛同する人たちは、ビットコインを通貨として流通させるため、ビットコインを現実のお金で取引できるサービス(※3)を公開しました。新しいビットコインを採掘するためには、ある程度の計算パワーが必要だったため、その計算にかかる電気代をベースとして、1ドルあたり1,000 BTC前後で取引が開始されはじめました。 ビットコインと現実の通貨が交換できるようになると、次第にそのユースケースが登場していきます。特に世間から注目を浴びた例として、2010年11月に起きたWikiLeaksスキャンダルや、2011年頃のシルクロードという取引サイトへの糾弾が挙げられます。 WikiLeaksによってアメリカの外交機密文書が公開された事件が発生した際、WikiLeaksに対する制裁として、PayPalを用いたWikiLeaksに対する送金が停止されたり、WikiLeaks創設者の銀行口座が凍結されたりといったことが行われました。WikiLeaksの是非は別として、特定の民間企業によって資産の移動を凍結されてしまう事態に対して反発が起こり、一方でビットコインを用いたWikiLeaksへの募金は止められなかったため、「送金の自由を誰にも止めることができない」というビットコインの性質に注目が集まりました(※4)。 また、シルクロードというサイトでは、匿名で送金が可能なビットコインを用いて違法な薬物が取引されていたり、マネーロンダリングに悪用されていたりする実態が糾弾されましたが、それらのニュースを通じてビットコインへの関心も高まり、2011年には1 BTCが30ドル以上で取引されるなど、最初のビットコインバブルを迎えました。 ※2: Satoshi’s posts to Cryptography mailing list ※3: New Liberty Standard ※4: Could the Wikileaks Scandal Lead to New Virtual Currency? ※5: Schumer Pushes to Shut Down Online Drug Marketplace アルトコインの誕生 ビットコインへの関心の高まりとともに、ビットコインの仕組みを流用した新たな暗号資産も登場し始めます。ビットコインの採掘や送金は、約10分に1回行われるブロック生成ごとにおこなわれますが、この間隔を短くして高速にトランザクションを実行できるようにした「ライトコイン」(※6)や、ビットコインにDNSの機能を付加した「ネームコイン」(※7)など、さまざな改良や改変をおこなったコインが発行されました。これらを総称して、「アルトコイン」と呼ばれます。 初期のアルトコインは、ビットコインのプログラムをフォーク(コピー)してきて、必要な改変をおこなったあと、賛同者たちでその改変プログラムを実行する形で発行されました。しかしこのやり方は、新しいコインの発行や維持する賛同者たちを多く集める必要があり、ハードルの高いものでした。 そこで、新たにプログラムをフォークして動かすことなく、より簡単に独自のコインを発行できるプラットフォームとして、Mastercoin(Omni)(※8)やCounterparty(※9)なども登場しはじめました。 ※6: Litecoin ※7: Namecoin ※8: Omni Layer ※9: Counterparty イーサリアムの誕生 ビットコインに続いてさまざまなアルトコインが登場する中で、大きな転換点となったのが、2015年のイーサリアム(※10)の登場です。 ビットコインをベースとした派生コインの多くは、あらかじめ決められた送金処理などを実行することはできますが、その表現力は限定的でした。そこでイーサリアムは、ビットコインが発明したブロックチェーンという仕組みを拡張し、ブロックチェーンの上で汎用的なプログラムを実行するためのプラットフォームの実現を目指しました。 イーサリアムを用いることで、ユーザーはわずか数十行のプログラムを記述してデプロイするだけで、独自の暗号資産をブロックチェーン上で実現することができるようになりました。 このように、新たな暗号資産を発行するハードルが劇的に下がる一方で、成功した暗号資産は初期の値段から数百倍~数万倍の価値に跳ね上がることも珍しくなく、一つのプロジェクトで数億円~数百億円の資金調達が実現されるなど、多くの投資資金が暗号資産に流入していきました。 ※10: Ethereum DApps, NFT, DeFiの誕生 イーサリアムを用いると、独自の暗号資産の発行だけでなく、汎用的なプログラムそのものをブロックチェーン上で動かすこともできるようになりました。 例えば、ある既存の暗号資産と、自身で発行した独自の暗号資産を交換するために、どこかの取引所サービスでその暗号資産を取り扱ってもらう必要はなく、イーサリアム上のプログラムで自動的に暗号資産同士の交換をおこなうことができます。そのような、ブロックチェーン上の取引所をDecentralized Exchange(DEX)と呼びます。 また、暗号資産を用いたギャンブルのようなサービスをブロックチェーン上で動かすこともできますし、より複雑なゲームロジックを実装することも可能です。 イーサリアム上のプログラムはスマートコントラクトと呼ばれ、スマートコントラクトを用いたアプリケーションはDecentralized Apps(DApps)とも呼ばれます。 イーサリアム上でさまざまなスマートコントラクトが開発されるようになると、類似の用途のコントラクトは共通規格化して統一的に扱いたくなります。そのような統一規格として、Fungible Token(FT)と呼ばれるトークン規格であるERC20や、Non-Fungible Token(NFT)と呼ばれるトークン規格であるERC721などが策定され、次第にイーサリアム上でDAppsを開発するエコシステムが整っていきました。 さまざまなDAppsの中で、特に影響の大きかったサービスの類型として、Decentralized Finance(DeFi)サービスが挙げられます。DeFiとは、大まかには暗号資産を対象とした金融商品を実装したり取引したりできるDAppsサービスの総称です。DeFiの登場により、将来価格が上がりそうな暗号資産に投資をするだけでなく、保有している暗号資産を誰かに貸し出して金利を得たり、複数の暗号資産のデリバティブ取引を組み合わせてリスクヘッジをしたりといった資産運用を、銀行や証券取引所を介することなくブロックチェーン上で行うことができるようになりました。 DeFiを用いた暗号資産の運用は、年利10%から数百%を上回ることもあり、より多くの投資資金を集めるきっかけとなりました。 ポスト・イーサリアム争い~現在 ビットコインやイーサリアムの歴史は、これまで説明したような成功や進歩の歴史だけでなく、違法取引やマネーロンダリング、消費者被害、環境への悪影響など、さまざまな負の側面も持っています。 短い紙面ですべての課題を解説することはできませんが、ここではイーサリアムの技術的課題と解決へのアプローチの潮流について簡単に紹介します。 さまざまなDAppsサービスがイーサリアム上で開発・運用されるとともに、ブロックチェーンのスケーラビリティ問題が深刻化していきました。 スケーラビリティとは、システムが処理すべきタスクの増大に対して対処可能な特性のことです。一般的な分散システムでは、システムを構成するノードを追加していくことで、タスクを分散処理してシステム全体の処理能力が向上できるようなアプローチを取ります。 しかし、古典的なブロックチェーンのアーキテクチャでは、いくらシステムを構成するノードを追加しても、システム全体として処理できるタスク量は増加しません。初期のイーサリアムの仕組みでは、秒間10-20トランザクションを処理することが限界でした。VISAクレジットカードのネットワークが秒間24,000トランザクションを処理可能(※11)であることと比較すると、イーサリアムのパフォーマンスは世界規模のトランザクションを処理する性能を満たせていません。 このスケーラビリティ問題は、2023年現在でも解決できていない課題の一つですが、大きく分けて2つの潮流があります。 一つは、スケーラビリティを兼ね備えた新しいブロックチェーンプラットフォームサービスを開発し、イーサリアムを超えていこうとする潮流です。代表的なプロジェクトとして、Solana(※12)やPolkadot(※13)などが挙げられます。イーサリアムの直面した課題をゼロベースで解決していこうとする場合が多く、必ずしもイーサリアムと互換性を保っているわけではありません。 もう一つは、既存のイーサリアムをLayer-1として、その下位に位置するLayer-2チェーンを接続し、イーサリアム自体にスケーラビリティ特性を付加しようとする潮流です。代表的なプロジェクトとして、Arbitrum(※14)やOptimism(※15)、zkSync(※16)などが挙げられます。 これらの技術はまだまだ発展途上であり、暗号資産の時価総額から考えても、ビットコイン、イーサリアムに続く第3のブロックチェーンサービスは流動的です。 本連載の中では、数あるブロックチェーンサービスの中でもある程度の地位を固めたと考えられるビットコインとイーサリアムについて、それぞれのオンチェーンデータを深掘りしていく予定です。 ※11: Visa ※12: Solana ※13 Polkadot ※14: Arbitrum ※15: Optimism ※16: zkSync オンチェーンデータ分析のすすめ 最後に、データ分析のスキルを学ぶ上で、オンチェーンデータが題材として適していると筆者が考えているメリットをまとめます。 まず、データ分析するために使えるリアルなデータが、誰でもアクセスできる状態で豊富に蓄積されている点がメリットとして挙げられます。 多くのサービスで蓄積されているデータの権利は、そのサービスを運用している企業や団体に帰属しており、一部の例外を除いて自由に閲覧したり活用したりできる状態にはありません。そうしたサービスのダミーデータを生成して練習することもできますが、人為的に生成されたデータと、実サービスで多くの人々によって蓄積されたデータとでは、得られる情報量に大きな違いがあります。 また、オンチェーン分析のためのツール群が充実している点も、初学者にとっては大きなメリットとなります。 例えば、Google BigQueryでは、ビットコインやイーサリアムなどの主要なブロックチェーンのトランザクションデータが、パブリックデータセットとして簡単にアクセス可能な状態で提供されています(※17)。ブロックチェーンデータ分析のための専門ツールを提供しているDune Analytics(※18)では、イーサリアムのトランザクションデータに対してSQLを用いて集計したり、ダッシュボードとして可視化したりする機能を無料で提供しています。 これらのサービスを用いることで、環境構築やデータの準備にほとんど時間をかけることなく、低コストでデータ分析の演習を始めることができます。 さらに、ブロックチェーンを用いたサービスを提供している企業や団体の多くは、こうしたオンチェーン分析に対する需要も高く、学習からコミュニティへの貢献までの距離感が非常に近いこともメリットとして挙げられます。 一般的な業界では、SQLを数週間から数ヶ月程度学んだ人が、いきなり実践的な成果を出せるケースは多くないでしょう。一方、ブロックチェーン界隈の現状では、プロジェクトの数に対してオンチェーン分析を行えるスキルを持った人材が圧倒的に不足しているため、初学者であっても実践的な成果を出すチャンスが多くあります。 ブロックチェーンサービスのエコシステムでは、オンチェーン分析の成果に対してグラントのような報酬を設定しているプロダクトも多く存在しているため、そういったグラントの獲得を目標に設定して学習するというのも、モチベーションを維持するために有効な手段です。 今回の記事でオンチェーン分析に興味を持っていただいた方は、ぜひ第2回~8回の記事も参考にしていただき、ブロックチェーンに対する理解やSQLのスキルを磨いていただければ幸いです。 ※17: Google Cloud Datasets ※18: Dune Analytics The post 【第1回】ブロックチェーンとは first appeared on Sqripts .
アバター