waveさんの技術日誌

wave1008の日記の新館です。

業務アプリケーションのテストの話(その2):テストフェーズはテスト計画の中で定義する

開発フェーズの用語の混乱

システム開発のフェーズ(工程)に関する用語は混乱しています。統一されていないという言い方もできます。

たとえば、要求定義、要件定義は日本語ではそれぞれ別のような意味付けをされていても英語では共に requirements definition らしいです。

外部設計は基本設計あるいは概要設計と呼ばれたり、内部設計は詳細設計と呼ばれたりします。システムの方式設計はアーキテクチャ設計と呼ばれたり、基本設計と呼ばれたりすることがあります。「外部設計」と「システム方式設計」がそれぞれ「基本設計」を名乗るのは混乱以外の何物でもありません。そもそも「基本」って何?ってことが曖昧です。

また、同じ用語を使っていたとしても、組織や個人によってその言葉の定義が微妙にずれていることがあります。したがって、プロジェクト計画時や契約時に各工程の成果物の定義とカバーする内容を、成果物の名前だけでなく、その書きっぷりに踏み込んで合意しておかないと、納品時の揉め事の原因になります。

テストのフェーズに関する用語も同様に不統一です。しかし、テストにおいてはより複雑です。正確には、プロジェクトの前提条件を考慮した上で、全体テスト計画を立案する中でテストフェーズを定義し、関係者で認識を合わせる必要があります。

テストのフェーズを定義する際に意識すべき要素として以下のものがあります。

  • テストレベル
  • テスト環境
  • テスト実施組織

テストレベル

システムの部品同士を接続することを結合、または統合といいます。最も小さな部品から始めて段階的に結合(統合)しテストしていくことをボトムアップテストと呼びます。また、結合(統合)したときのテスト対象の粒度でテストを分類したものをテストレベルと呼びます。具体的には単体テスト結合テストシステムテストなどがあります。テストフェーズはまず、これらのテストレベルに対応して計画を開始し、単体テストフェーズ、結合テストフェーズ、システムテストフェーズとします。

ただし、システムテストフェーズは総合テストフェーズと呼ばれることが多いため、以下では総合テストフェーズとします。

テスト環境

テストを実施する環境はテストフェーズを細分化したり統合したりする要素となります。テスト環境は具体的には以下のようなものがあります。

開発環境(ベンダ内)

  • 開発者のPC
  • 開発用サーバー(群)

結合テスト環境(ベンダ内)

  • テスターのPC
  • 結合テスト用サーバー(群)
  • 性能テスト用サーバー(群)

結合テスト環境(顧客内)

総合テスト環境(顧客内)

  • 総合テスト(業務シナリオテスト)用サーバー(群)
  • 総合テスト(性能テスト)用サーバー(群)

運用テスト環境(顧客内)

  • 運用テスト用サーバー(群)

本番環境(顧客内)

  • 本番用サーバー(群)

テスト実施組織

これらの環境の上で、誰が、何をテストするのか作業計画を行うことでテストフェーズが定まります。誰が、何をテストするのかは、会社組織やプロジェクトによって決まります。

テストフェーズの例(自社サービス開発)

たとえば自社サービスを開発してクラウドに公開しているような企業で、製品開発チーム、テストチームが常時設置されているとすると、テストフェーズを以下のように定義することができます。

単体テストフェーズ

  • 開発用PC、開発用サーバー(群)で実施する
  • 開発者がxUnitでクラスを自動テストする

結合テストフェーズ

  • 開発用PC、開発用サーバー(群)で実施する
  • 開発者が画面・帳票・バッチを手動でテストする

総合テストフェーズ

  • テスト用PC、総合テスト用サーバー(群)でテストする
  • テストチームが画面・帳票を手動でテストする
  • 開発者がバッチを手動でテストする

この例ではxUnitを使用してクラスを自動テストする工程を単体テストフェーズ、画面・帳票・バッチのようにアプリケーションとして操作可能なものを手動でテストする工程を結合テストフェーズとしています。これは単体=クラスという考え方に基づいています。

一方、単体=機能(画面・帳票・バッチ)ととらえる考え方もあり、SIerの場合は単一の機能をテストするのを「単体テストフェーズ」、機能をいくつか組み合わせてテストするのを「結合テストフェーズ」と呼ぶことが多いと思います。この場合、単体=クラスの意味での単体テストは実施しないことがあります。

テストフェーズの例(受託システム開発

別の例として、システムを受託開発で構築する場合は、自社、顧客、他ベンダと協力してテストを計画する必要があります。この場合、例えばテストフェーズを以下のように定義することができます。

単体テストフェーズ

  • 開発用PC、開発用サーバー(群)で実施する
  • 開発者がxUnitでクラスを自動テストする ※実施しない場合もある
  • 開発者が個々の機能(画面・帳票・バッチ等)を手動でテストする ※こちらは必ず実施する

内部結合テストフェーズ

  • ベンダ内の結合テスト用PC、結合テスト用サーバー(群)で実施する
  • ベンダ内のテストチームが機能(画面・帳票・バッチ等)を組み合わせたシナリオをもとに手動でテストする

外部結合テストフェーズ

  • 顧客内の結合テスト用PC、結合テスト用サーバー(群)で実施する
  • 自社の開発者と、他社の開発者が、互いに対向するシステムとのインターフェースを手動でテストする

総合テストフェーズ(業務シナリオテスト)

  • 顧客内のテスト用PC、業務シナリオテスト用サーバー(群)
  • 顧客内のテストチームが画面・帳票を手動でテストする
  • 開発者がバッチを手動でテストする

総合テストフェーズ(性能テスト)

  • 顧客内のテスト用PC、性能テスト用サーバー(群)
  • ベンダの性能評価担当者が画面・帳票・バッチを性能評価する 

この例では、テストレベルが「結合テスト」とされる機能(画面・帳票・バッチ等)が開発者によって単体テストフェーズで実施されます。その他の部分はシステム間のインターフェースによって区切られるベンダの担当範囲によって、内部結合テストフェーズと外部結合テストフェーズに分割して実施されます。

 

このように、自社の中で閉じた開発と、顧客や他のベンダと作業分担して行う開発とでは、テストフェーズの定義の仕方が大きく異なります。

結合テスト」という用語を使ったとき、相手は違う内容を思い浮かべているかもしれません。認識齟齬があると後に問題が発生したときに揉める原因となります。

 

したがって、特定のテストフェーズの意味を確認してから関係者とテストに関する調整をすることが大変重要です。

 

業務アプリケーションのテストの話(その1)

テストについて書いていく

ブログ更新するのは一年ぶりです。システム開発の上流工程と下流工程を行ったり来たりして、それなりに楽しいエンジニアライフを過ごしています。これまでテストに関する記事を書いたことはありませんが、ネタがそろってきたので書いて行こうと思います。

 プログラマはテストが苦手

プログラマはテストに対して苦手意識を持っていたり、必要性はわかるんだけど面倒なのであまりやりたくないと考えたりしがちです。おそらく背景には

  1. テストに関する十分な教育を受けていない。作るのは好きでも、テストへの興味が薄いので自分で勉強しようとしない
  2. 自分が作ったコードの欠陥を自分で発見するのは、先入観があるので難しい
  3. プログラマの最大の関心事は品質ではなく、納期を遵守した製品のデリバリー

といったことがあると思います。

規模が小さいプロジェクトだと、少数のエンジニアで開発もテストも兼務してやることが多いと思います。一方で、テスト専任者またはテストチームを設置することで上記の2と3はある程度解決します。作業を分担することで開発者の負担を減らせるうえ、期間短縮および第三者の視点による品質向上が期待できるでしょう。

一方で、1の「テストに関する十分な教育を受けていない」という問題はわりと根深い問題です。諸先輩方も含め、テストタスクのあるべき姿をきちんと指導できる人は少なく思います。 

 テストが好きな人

個人的には、開発が大好きな人にはたくさんお目にかかれても、テストが好きで好きでたまらないという変態(暴言)にはお目にかかる機会はあまりありません。ただし、テストに向いている人というのは、ある種の特性を持っている気がします。

  • コツコツやるのが得意。マメである
  • 品質向上に貢献できると嬉しい
  • 物事の不備を指摘することに躊躇がなく、性格が悪い(いい意味で)
  • 独創的で、たまに他人が思いつかないような視点で不具合を見つけることがある

 こうして列挙してみると、基本的にせっかちなプログラマという人種とは真逆の存在に思えなくはないです。

独立したテストチームの有効性

システム開発の現場においては、開発チームとは別に独立したテストチームを設置すると品質は向上する傾向があります。開発チームは製品を産み出すことに、テストチームは品質確認に、それぞれ集中できます。

また、テストチームがテスト仕様書を作成する過程で、要件定義書や外部設計書に対する第三者レビューの効果があり、設計不備を早期に発見することにつながります。

なお、テストチームが担うテスト工程は結合テスト以降であり、 単体テストは実装担当の開発者自身が行います。

 

 

1回目は以上です。それなりに書くのは疲れます。

次回は混乱するテスト工程の呼び方について書こうと思います。

 

Node.jsでexceljsを使う(その1)

Node.jsでExcelの処理をしたいと思いました。

いろいろライブラリがあるのですが、APIが直感的なのでexceljsがよさげだと思いました。

https://www.npmjs.com/package/exceljs#reading-xlsx

でも、このドキュメントはちょっと不親切なので、初心者にはわかりにくいです。そもそもNode.jsそのものに慣れていないので、非同期I/Oの扱いがよくわからんでかなり悩みました。以下の記事を読んでPromiseパターンを理解すると、だんだん書き方が分かってきました。

 

参考にした記事

俺たちはJavaScriptの非同期処理とどう付き合っていけば良いのだろうか - Qiita

JavaScript Promiseの本

 

試しにTypeScriptでサンプルコードを書いてみました。


// exceljsで複数のExcelファイルを読み込んでファイルとシートの一覧を作成する
// TypeScriptのサンプルです。

import * as Excel from 'exceljs';
import * as path from 'path';
import * as fs from 'fs';

// 処理対象のExcelファイルのリストを作成します。
let dataDir = path.resolve("testdata");
let filelist = fs.readdirSync(dataDir).map(f => { return path.join(dataDir, f); });

// exceljsはファイルの読み込みに非同期のメソッドしか提供していないので、promiseパターンで実装します。
// まず、ファイルリストに対応してWorkbookの読み込みを行うPromiseのリストを作成します。
let promises = filelist.map(file => {
    let workbook = new Excel.Workbook();
    return workbook.xlsx.readFile(file) // readFileはPromiseを拡張したPromishを返します。
        .then(() => {
            // workbookにはfileの情報が含まれないので、fileとペアにしてresolveします。
            return Promise.resolve({ file: file, workbook: workbook });
        });
});

// すべてのPromiseを実行します。
Promise.all(promises)
    .then(function (results) {
        // ファイル、シートID、ワークシート名をコンソールに出力します。
        results.forEach((x) => {
            let workbook = x.workbook;
            workbook.eachSheet((worksheet, sheetId) => {
                console.log(x.file + "," + sheetId + "," + worksheet.name);
            });
        });
    }).catch(function (err) {
        console.log(err);
    });

実行結果

f:id:wave1008:20170524012314p:plain

 

いい感じじゃないですか。

exceljsでExcelの処理がどこまでできるか興味あります。

 

オッサンが始めるAngular(その1):Hello World

Angular 2に入門しようと思ったらいつのまにかAngular 4になっていました。

時の流れは早いものです。

Angularのチュートリアルで勉強します。

 

エディタの用意

Angularをインストールするまえに、エディタをインストールします。エディタは好きなもの使えばいいですが、ここではVSCodeを使ってみます。

 

f:id:wave1008:20170511232028p:plain

f:id:wave1008:20170511232055p:plain

f:id:wave1008:20170511232102p:plain

f:id:wave1008:20170511232111p:plain

f:id:wave1008:20170511232118p:plain

f:id:wave1008:20170511232123p:plain

f:id:wave1008:20170511232127p:plain

f:id:wave1008:20170511232143p:plain

 

 

CLI QUICK START

AngularのチュートリアルCLI QUICK STARTをやってみます。

CLI Quickstart - ts - CLI-QUICKSTART

f:id:wave1008:20170511232859p:plain

 

【超手抜き翻訳】 

Angular CLIはAngularで開発する際に利用するコマンドラインインターフェースです。

このガイドの目的はAngular CLIを使用してTypeScriptで記述したAngularのアプリケーションをビルド・実行することです。

以下のステップで説明します。

  1. 開発環境のセットアップ
  2. プロジェクトとスケルトンアプリケーションの作成
  3. アプリケーションの実行
  4. アプリケーションの編集

 

Step1. 開発環境のセットアップ

Node.jsとnpmをインストールします。最低でもnode 6.9.x, npm 3.x.x を使用してください。

https://nodejs.org/en/download/

f:id:wave1008:20170511233618p:plain

 

f:id:wave1008:20170511233643p:plain

f:id:wave1008:20170511233650p:plain

f:id:wave1008:20170511233655p:plain

f:id:wave1008:20170511233659p:plain

f:id:wave1008:20170511233704p:plain

f:id:wave1008:20170511233708p:plain

 

 nodeとnpmのバージョンを確認。

f:id:wave1008:20170511233945p:plain

 

Angular CLIをグローバルにインストールしてください。

f:id:wave1008:20170511234249p:plain

 

f:id:wave1008:20170511234307p:plain

完了。

 

Step2. 新規プロジェクトの作成

ng newコマンドでプロジェクト(my-app)とスケルトンアプリケーションを作ります。

f:id:wave1008:20170511234449p:plain

 

しばらく待ちます。長い。

f:id:wave1008:20170511234613p:plain

 

 my-appの下にいろいろ生成されています。

f:id:wave1008:20170511234715p:plain

 

Step3. アプリケーションの実行

プロジェクトのディレクトリへ移動し、サーバーを起動しましょう。

ng serveコマンドでサーバーを起動します。

f:id:wave1008:20170511234838p:plain

 

ブラウザでアプリケーションが開きます。

f:id:wave1008:20170511234917p:plain

 

Step4. Angularのコンポーネントを編集する

my-app\src\app にapp.component.tsが生成されています。(中身はTypeScript)

f:id:wave1008:20170511235148p:plain

 

app.component.tsをVSCodeで開きます。

titleのテキストを'My First Angular App'書き換えます。

f:id:wave1008:20170511235225p:plain

 

保存すると、ng serveがファイルの変更を検出してリビルドが実行され、ページがリロードされます。

f:id:wave1008:20170511235341p:plain

 

同様に、app.component.cssを編集します。

f:id:wave1008:20170511235502p:plain

 

保存すると、ng serveがファイルの変更を検出してリビルドが実行され、ページがリロードされます。

f:id:wave1008:20170511235631p:plain

 

 

CLI QUICKSTARTは以上です。

 

 

 

 

ドキュメントのバージョン管理はSVNとGit、どっちがいいの?

SVNからGitへの移行を考えたんだけど…

10年ほど前にバージョン管理ソフトウェアとしてSVN(TortoiseSVN)を使い始めました。現在はドキュメントもソースコードもバージョン管理なしの世界には戻れないなと感じています。世の中的にGitが流行っているのは知ってたんだけど、職場でもGitに移行するって話は具体化しなかったし、いろいろ不便はあったけどSVNに慣れちゃってたんで、Gitの導入はしてませんでした。久しぶりに技術ブログを書くにあたって、サンプルコードを共有するならGitHubがいいかなーと思い、ようやく使い始めたところです。

なるほど、GitはオリジナルのリポジトリをローカルPCにコピー(クローン)して、ローカルで一旦コミットしてから、オリジナルにプッシュするという二段構えの構成になっている。個人の作業は成果物が完成するまでローカルで進めるので、マージの衝突頻度が緩和されるんですね。また、ローカルで履歴管理できるので、SVNで不満だった「作業中のものを適宜コミットして履歴管理に乗せたいけど、未完成のものをコミットすると他の開発者に迷惑をかける」って問題が解決されてます。SVNだと履歴管理したいなーってタイミングでパッチファイルを作って、SVNの一時フォルダにコミットすることで履歴管理の代用とするなんてダサいことをやってました。TFSだとシェルブ機能で一時保存できるらしいので、あれはあれで便利そうですけどね。

なんか、Gitいいかもって思ったので、ソースコード管理だけでなくTortoiseGit使ってドキュメント管理もSVNから移行しようかなってちょっと考えたんだけど、結論から言うと思い留まりました。GitはSVNと比較すると、ドキュメント管理に向いていないと思います。理由は以下。

 

個人的にGitでのドキュメント管理を避ける理由

  1. 空フォルダを作成できない
  2. ファイルをロックできない
  3. プッシュしないと中央のリポジトリに反映できない

 

1.空フォルダを作成できない

Gitは空のフォルダを作成することができません。理由は知りません。この制約を回避するために、なんでもいいからファイルを一つ置くということが必要です。一般には.gitkeepという名前の空ファイルを置くのがプラクティスなんだそうです。

ドキュメント管理するのに何で空フォルダを使いたいのかって?それは、プロジェクト開始時にドキュメントの保管場所としてフォルダ階層を一式登録し、そこに置くようにルール化したいからです。よくありますよね、こんなの。

  • 01.プロジェクト計画
  • 02.要求分析
  • 03.要件定義
  • 04.外部設計
  • ...

フォルダ階層の末端に.gitkeepなんてファイル置きたくないです。

 

2.ファイルをロックできない

SVNのファイルロック機能は、ファイルを読み取り専用にすることでロックされている状態を擬似的に実現しているだけの簡易なものですが、無いよりもマシです。企画書や報告書なんかを複数人で編集する際、ロックを取得してから(読み取り専用を書き込み可能にしてから)編集するというワークフローになっていると、編集者どうしが自然に協調して作業することができます。

一方、Gitにはロック機能がありません。そもそも分散型なので、排他機能を実現しようがありません。ドキュメント管理はSVNのような集中型が向いていると思います。

 

3.プッシュしないと中央のリポジトリに反映できない

これが一番問題な気がします。AさんとBさんが同じ報告書.pptxを編集していたとして、Aさんが編集した結果をBさんが取得しようと思ったら、Gitだと以下の手順になります。

  1. Aさんが報告書.pptxをコミット(ローカル)
  2. Aさんが報告書.pptxをプッシュ
  3. Bさんが報告書.pptxをプル

 

Gitのことをよく理解して使いこなしているエンジニアならともかく、ドキュメントを中心に仕事をしている人なら、コミットしたらそこで安心して、プッシュするのを忘れますよね。で、「企画書コミットしましたー」「プルしても落ちてこねえよ。ちゃんとプッシュしたのかよ」なんて会話が想像できますよね。

そもそも、テキストファイル以外のドキュメントはソースコードのようにはマージできないから、pptxとかxlsxとかの非テキストファイルはコミットとプッシュを二段階に分ける必要ないんですよね。コミットした時点で衝突がわかればそれでいい。集中型のSVNはそのような挙動なわけで、そこからあえて分散型のGitのフローに移行するメリットはないんじゃないかと思います。

 

以上のことから、ドキュメント管理はSVNのほうがいいと思うんです。サーバー管理がめんどくさいかもしれないけど、ドキュメントはSVNで、ソースコードはGitでやるのがよいと思われ。実践してないから知らんけど。

 

技術ブログ再び

数年のブランクを経て、久しぶりに技術ブログを書こうという気になってきたので、ぼちぼち始めます。といっても、サボっていたぶん世の中のトレンドにキャッチアップできていないところ多々有り。興味の対象もMSテクノロジーからすっかりオープン系に移ったところで、さしあたってはnodeとか、Angularとか、Seleniumなんかを掘り下げて行こうかなって思っています。