投稿日 2009年8月24日 月曜日 カテゴリ ソフトウェア開発, プロジェクト管理 投稿者 syojiコメントは受け付けていません。 

バグのライフサイクルを管理する仕組みがバグトラッキングシステムの特徴の1つである。

簡単に言うと、「バグの発生~調査~対策~確認」のバグ1件毎にステータスを管理する仕組みのことである。

なぜ、バグのステータスを管理必要があるか、というとExcelをつかったバグ管理を実践してみるとわかると思う。

こちらの記事(「とりあえずバグ管理」のための Excel テンプレート)

でバグ管理に必要な項目をリストアップしたが、バグの「状態」をもう少し運用に沿った仕組みで管理したくなる。

Excelを使ってバグ管理の運用をしていくと以下のような課題が挙がると考えられる。

  • いつ、だれが、どのような対応をしたのか?わかりにくい
  • 対応履歴の管理が出来ない
  • 状態の変更履歴(どのようなフローを経由してきたか)がわからない
  • Excelファイルをメール添付してやりとりするため、最新がどれかわからない
  • 複数の版にわかれたファイルをマージしなければいけない
  • YYYYMMDD_○○○.xls という管理になってしまう

など、Excelではバグ管理できないわけではないが、開発者にとっては運用するだけでストレスを感じてしまう場合が多い。

弊社ではバグトラッキングシステムを利用しているが、これは開発者にストレスをかけないために導入したという経緯があるためである。

これまでの経験上、Excelで運用していくと破綻してしまう場合があるので、バグトラッキングシステムはソフトウェア開発では必須のツールになっている。

バグトラッキングシステムの中で最も必要な機能が「状態(ステータス)」とワークフローである。 以前にブログで紹介した、「ソフトウェア開発:バグ管理方法の紹介」で簡単にワークフローについてイメージ図を紹介したが、バグのフローとは

  • 1. バグの発生(発見者)
  • 2. 担当者への振り分け
  • 3. 担当者の対応
  • 4. バグの完了確認(対応済みかどうか)
  • 5. バグの完了

である。 ソフトウェア開発の現場では、バグの数も半端な数ではなく大量に発生する。それらバグ1つ1つのワークフローをきちんと管理できる仕組みがバグトラッキングシステムの大きなメリットであると考えている。

会社やプロジェクトによって、ワークフローはもっと複雑になっていると思うが、

基本的には

[発生->割当->対応中->確認待ち->完了]

[         ->対応なし             ]

が管理できれば十分である。

今回はバグの場合のワークフローについて書いたが、機能追加の要望、タスクなども同様にワークフローを決めて運用することでソフトウェア開発の効率は格段に上がると思う。

OpenGrooveの社内検索システム : zeera document search

zeera document searchで社内文書検索

対応履歴の管理が出来ない
投稿日 2009年8月17日 月曜日 カテゴリ Apache, ソフトウェア開発, テスト 投稿者 syojiコメントは受け付けていません。 

Webアプリケーションやクライアントサーバ型のシステム開発の中で性能要件を満たすために負荷試験やロード試験といわれる工程がある。

重要な工程として考えているが、スケジュールの厳しいプロジェクトなどでは後回しにされることがあった。 特に、開発が遅れている場合、要件を満たすための開発が重視されることは理解しているが、負荷試験を実施することは同じくらい大切な工程である。試験で起こることは当然、本番環境でも起こり、あとで痛い目をみないためにも必須の工程である。

負荷試験を設計する上での考え方をまとめてみたいと思う。 以下のサイトが参考になる。

負荷試験とは

構築するシステムがどの程度の負荷に耐えられるかを測定し、システムの信頼性と耐用範囲を明確にする。ウェブアプリケーションの場合、同時アクセスユーザ数をどれだけ処理出来るか、閾値を越えた場合のシステムの振る舞いを検証する試験である。

負荷試験で使われる試験環境は本番環境と同一であることが望ましい。しかし、実際には機器調達が難しいことが多い(例えば、想定している分だけのクライアントマシンを用意する等)。機器が準備できない場合、サーバに負荷を発生させるツール等を使用し、高負荷、過負荷を与え、システムの振舞いについて検証する。

負荷試験の計画(設計)に必要なこと 負荷試験を計画するときに最低限、考えなければいけないことを説明したい。

前提条件

試験を実施するときの試験環境について、サーバの役割、台数、クライアント数、負荷をかける時間等の環境について条件を明確化しておく必要がある。

監視ポイント

例えば、Webアプリケーションの場合、クライアントがアクセスしトップページが表示されるまでの時間。など要件を満たすために必要な監視ポイントを明確にしておく必要がある。サーバサイドではDBに対する大量のI/O(書込、読み出し等)がそれにあたると思われる。

目的と対象範囲

負荷試験でクリアしなければいけない要件、ユーザ数などの試験の目的と対象範囲/ハード情報(各サーバのOS情報/CPU/DISK IO/MEMORY/NETWORK)、過負荷時の測定範囲を明確にする。

性能要件(目標値)

想定されるクライアント数から性能要件を予測し、定義する。レスポンス時間等の試験項目から測定可能な数値を予測する。 例えば年に1度のみ過負荷が発生するといった事象に合わせてシステムを組んだ場合、性能要件は十分であるが、コスト面で満足するものにはならない場合がある。そのため、要件にあった目標値を設定することは重要である。

想定シナリオ

構築するシステムの利用シーンを考えたシナリオを作成する。試験実施はそのシナリオに沿って行われるべきである。 例えば、メールクライアントの場合、社員が出社する時間(09:00頃)が大量のアクセスが発生する、など。その利用シーンをシナリオに組み込む。

実施方法

市販のツールを利用する、自作ツールを利用する、など目標値を達成するためには過負荷状態を作らなければいけない。疑似的に過負荷状態を作り出す必要がある。Webアプリケーションに限定されるが無料ですばらしいツールが多く提供されている。

試験結果

負荷試験計画時の「目的と対象範囲」を達成したかどうか、 実測値が予測値より悪い場合や、目標値ギリギリの場合、チューニングを実施することになる。 問題点の原因については、計測データなどを使って

  • トランザクション数/クライアント数が増加しているとき、スループットの増加傾向が変化した時点
  • レスポンスタイムが急速に遅くなった点

分析するポイントとして、システムの測定値が急激に変化したとき、関連するモジュールがボトルネックと考えられる。 チューニングについては、そのようなボトルネックと予測されるモジュールから優先的に検証する必要がある。

以上のような点について、負荷試験の計画フェーズで考えておけば良いのではないかと考える。 負荷試験が実施されるのはシステムが構築され、結合試験も終わった以降になる。一番忙しいフェーズであるが 負荷試験の重要性を説明し、しっかりと計画をして実施していきたいと思う。

投稿日 2009年8月10日 月曜日 カテゴリ ソフトウェア開発, プロジェクト管理 投稿者 syojiコメントは受け付けていません。 

Peace Pipe: 効率の良いコードレビュー [software] を読んでソースコードレビューの必要性について考えてみたい。

ソースコードのレビューをやっているか?

ツールなどを使ったソースコードチェックは多くのSIerで行われていると思うが、ここではソースコードレビューについて。 プロジェクトによっては「全くやっていない」「重要なプログラムだけ選んでやっている」など、プロジェクトの状況、状態によって異なると思う。

自分の過去の開発経験では、プリントアウトしたソースコードを2人で組になって読み合わせをした。

  1. 1. 開発者がレビュアにロジックを説明する。
  2. 2. レビュアーは疑問に思ったことを聞く。
  3. 3. ここで、機能的な不具合、アルゴリズム、モジュール分割をみる

時間的な制限があるためすべてのコードについて実施できない場合がほとんどだったため、レビュー対象となるソースコードは次のような点を考慮してレビュー対象を決めていた気がする。

  • 特定の担当者が作成したコード
  • 共通モジュール
  • サーバサイドのコード
  • ソースコード(処理)が複雑であるコード(プロジェクトによって複雑度は異なる)
  • ソースコードをざっと眺め、引っかかるコード、気になったコードを見つけた場合

ソースコードレビューについて、誰が行うか、観点は?の説明されている以下のサイトが参考になる。

IPA ISEC 第2章 脆弱性回避策とソフトウェア開発工程:ソースコードレビュー

観点

  • コーディング規約、命名規約に従っているか
  • 言語特有の技術的なノウハウに違反していないか
  • ロジックエラー、仕様違反していないか
  • 深すぎるネスト、巨大すぎる関数など・・・

ソースコードレビューの必要性として特に言われることとして、以下の2点がある。

「開発者のスキルが上がる」

開発者よりも高いスキルをもつレビュアが、ソースコードのレビューを行うことで、書き方の指導や考え方のトレースをすることになり、開発者のスキルを向上させることができる。 ソフトウェア開発では特にその”人”のスキルに依存しがちである。長い目で見て開発者のスキルを上げることが品質の良いシステムを開発する上で最も効果がある。

「ソースコードの質がよくなる」

ソースコードレビューによりバグを抽出することで品質が向上する。検出されなければいけない工程で確実に検出できることは必須であると思う。当然、前工程で検出されたバグ修正も少ないコストで可能である。 ソースコードが第三者の目に触れず、開発者だけが「正しい」と認識することは避けるべきであり、その仕組みをチーム内に作っておくことは重要である。 進捗ミーティングや報告会と同様にコードレビューを定着させるべきだと思う。

投稿日 2009年8月3日 月曜日 カテゴリ ソフトウェア開発, テスト, プロジェクト管理 投稿者 syojiコメントは受け付けていません。 

ソフトウェア開発プロジェクトでは、単体/結合/総合/受入試験と製品開発の工程により観点の異なる試験フェーズが存在している。

試験の目的の1つは、

「ユーザが利用しているとき、故障が発生しないよう、事前にあらゆる種類の故障を見つけておくこと」

である。 しかし、現実的に全てのバグを発見することは難しい。

そこで、「良い試験項目」を作成し、限られた時間内に多くのバグを見つけることを行う必要がある。 今回は試験工程(単体、結合、総合)で試験内容の粒度・観点について説明すると

それだけで相当な文書量になるため、「良い試験項目とは?」として押さえておかなければいけない点を説明したい。

「良い試験項目」とは

  • 試験実施の方法が説明してあること
  • 期待値(捜査の結果)が明示してあること
  • 「試験日、担当、結果」が記録されること
  • バグを発見できる可能性が高い内容であること
  • 重複がないこと
  • 単純すぎず、複雑すぎないこと

試験項目を作成するときには、工程や手法によって異なるが「ソフトウェアテスト – Wikipedia」で説明されている点と同じように、

「バグはどうやって発生するのか?」

を考えながら試験項目を作成するとうまくいく場合が多い。

また、バグデータベース(過去の失敗事例、バグトラッキングシステム/BTS)があれば、過去の事例からバグを分析してみると参考になることが多い。

開発の現場でよく発生する例として

本来なら前工程で検出されなければいけないバグが、後工程でみつかることがある。

「なぜ、見つけなければいけない工程で漏れてしまい、後工程で見つかったのか?」

をプロジェクトメンバーが考えることが品質の向上、次のプロジェクトの分析材料になっていく。

過去のプロジェクトの失敗事例や「なぜ、バグが漏れたのか?」をチームで考え、

共有していくことが品質管理の第一歩だと考えている。

zeera document search

zeera document search で仕事の効率アップ!

「バリバリ働きマン」「めんどくさがりさん」 zeera document search で仕事の効率Up!

投稿日 2009年7月30日 木曜日 カテゴリ Python, テスト 投稿者 sugimotoコメント(0) » 

sugimoto です。

Pythonの単体テストのツール unittest を使ってみました。

1. まずはマニュアル通りに。。

Python – unittestのマニュアルから、TestSequenceFunctions を実行します。

# python testsequecefunctions.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.002s

OK

普通に成功しましたね。

2. TestSuite を実行する

今度は複数のTestCaseからなる、TestSuiteを実行してみます。

TestCaseは同じものを使ったので、命名のセンスが悪くてすいません。。

2つのTestCaseをまとめて実行するTestSuite

[testsuite.py]

import unittest
import testsequecefunctions as TestSequenceFunctions
import testsequecefunctions2 as TestSequenceFunctions2

suite1 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions.TestSequenceFunctions)
suite2 = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions2.TestSequenceFunctions2)
suite = unittest.TestSuite([suite1, suite2])
print suite.countTestCases()

runner = unittest.TextTestRunner()
runner.run(suite)

実行すると

# python testsuite.py
6
......
----------------------------------------------------------------------
Ran 6 tests in 0.002s

OK

6個のテストがすべてパスしました。

3. trac plugin をテストしてみる

trac のestimationtools pluginをテストしてみます。すでにテストコードも提供されているので、今回は実行するだけです。

# unzip estimationtoolsplugin-r6309.zip
# cd estimationtoolsplugin/trunk/estimationtools/tests
# ll
total 24
-rw-r--r-- 1 root root 9264 Jul 29 11:18 burndownchart.py
-rw-r--r-- 1 root root 2696 Jul 30 10:46 hoursremaining.py
-rw-r--r-- 1 root root 2283 Jan 26  2009 workloadchart.py

そのまま実行できるようにスクリプトの最後に以下のコードを追加しておきます。

if __name__ == "__main__":
    unittest.main()

そして実行

# python burndownchart.py
Traceback (most recent call last):
  File "burndownchart.py", line 3, in ?
    from estimationtools.burndownchart import BurndownChart
ImportError: No module named estimationtools.burndownchart

エラーになりました。。

estimationtools.burndownchart がないということですね。。

plugin 本体のディレクトリにパスを通しておきます。

# export PYTHONPATH=/root/plugins/estimationtoolsplugin/trunk/

再度実行します。

# python burndownchart.py
...FFF......
======================================================================
FAIL: test_calculate_timetable_with_closed_and_reopened_ticket (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 140, in test_calculate_timetable_with_closed_and_reopened_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0), day4: Decimal(5)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 113, in test_calculate_timetable_with_closed_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(5), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("5"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket2 (__main__.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "burndownchart.py", line 126, in test_calculate_timetable_with_closed_ticket2
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

----------------------------------------------------------------------
Ran 12 tests in 0.478s

FAILED (failures=3)
#

今度はうまくいった。。と思ったら、なぜかテストが失敗しましたね。。

4. estimationtools plugin のtest suite を実行する

estimationtools plugin には3つのテストがあるので、すべて実行するためのスクリプトを作ります。

[testsuite.py]

import unittest
import burndownchart as burndownchart
import hoursremaining as hoursremaining
import workloadchart as workloadchart

runner = unittest.TextTestRunner()
suite = unittest.TestLoader().loadTestsFromTestCase(burndownchart.BurndownChartTestCase)
runner.run(suite)

suite = unittest.TestLoader().loadTestsFromTestCase(hoursremaining.HoursRemainingTestCase)
runner.run(suite)

suite = unittest.TestLoader().loadTestsFromTestCase(workloadchart.WorkloadChartTestCase)
runner.run(suite)

3つのテストをロードして、実行するだけです。簡単です。

実行してみます。

# python testsuite.py
...FFF......
======================================================================
FAIL: test_calculate_timetable_with_closed_and_reopened_ticket (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 140, in test_calculate_timetable_with_closed_and_reopened_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0), day4: Decimal(5)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0"), datetime.date(2009, 8, 2): Decimal("5")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 113, in test_calculate_timetable_with_closed_ticket
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(5), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("5"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

======================================================================
FAIL: test_calculate_timetable_with_closed_ticket2 (burndownchart.BurndownChartTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/plugins/estimationtoolsplugin/trunk/estimationtools/tests/burndownchart.py", line 126, in test_calculate_timetable_with_closed_ticket2
    self.assertEqual(timetable, {day1: Decimal(10), day2: Decimal(0), day3: Decimal(0)})
AssertionError: {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("0"), datetime.date(2009, 8, 1): Decimal("0")} != {datetime.date(2009, 7, 31): Decimal("0"), datetime.date(2009, 7, 30): Decimal("10"), datetime.date(2009, 8, 1): Decimal("0")}

----------------------------------------------------------------------
Ran 12 tests in 0.619s

FAILED (failures=3)
.....
----------------------------------------------------------------------
Ran 5 tests in 0.692s

OK
..
----------------------------------------------------------------------
Ran 2 tests in 0.126s

OK

1つめのテストケースはやっぱり失敗しますが、残りのテストケースはすべて成功しました。

今回は既存のplugin に添付されているテストケースを使いましたが、自分がpluginを作ったときもテストケースを書きたいと思います。

参考
« 前ページへ次ページへ »