レベル: 中級 Angel Rivera (rivera@us.ibm.com), Software Engineer, VisualAge TeamConnection, IBM
2001年 3月 01日 機能テストは、ソフトウェア開発には不可欠な部分です。すでにLinuxに ロード済み で使用可能なbashを使用すれば、機能テストを迅速かつ簡単に行うことができます。この記事では、Angel Riveraが、行コマンドを使用するLinuxアプリケーションで機能テストを行うための bashシェル・スクリプトの使用方法を説明します。このスクリプトは、行コマンドの戻りコードに依存しているので、この方法をGUIアプリケーションで使用 することはできません。
ソフトウェア・アプリケーションの開発サイクルにおいて、機能テストは、機能が期待通りに動作し、コードに関するすべてのエラーが適切に処理されていることを確認する段階で行われるテストです。通常これは、個々のモジュールに対する単体テストの後に、高負荷、高ストレスの条件下で行う製品全体に対する より詳細で完全なシステム・テストの前に実施されます。
市場には、テストを楽に行うための機能を満載したテスト・ツールが数多く出回っています。しかし、これらのツールは購入し、インストールし、そして構成しなければならず、このために貴重な時間と 労力が消費されてしまう可能性があります。bashを使用すると、さまざまなことを迅速に行うことができます。
bashシェル・スクリプトを使用した機能テストの利点:
- bashシェルは、Linuxシステムにすでにインストール済みおよび構成済みとなっています。これを準備するために時間を費やす 必要はありません。
- bashシェル・スクリプトは、viなどのすでにLinuxに入っているテキスト・エディターを使って 変更および修正することができます。テスト・ケースを作成するために、専用のツールを入手する必要はありません。
- すでにBourneまたはKornシェル・スクリプトの開発方法を知っていれば、bashシェル・スクリプトでの 作業を開始するのに十分な知識を持っていることになりますので、学習にあまり時間を使わないですみます。
- bashシェルは、非常にシンプルなものから、中レベルまでの複雑度のスクリプトを開発するための 豊富なプログラミング構成を提供します。
KornからBashへスクリプトを移植する際の推奨事項
既存のKornシェル・スクリプトをbashに移植する場合は、以下のことを考慮してください。
- Kornの "print" コマンドはbashでは使えません。代わりに "echo" コマンドを使用してください。
- スクリプトの最初の行を、
#!/usr/bin/ksh
から
#!/bin/bash
に変更する必要があります。
機能テスト用のbashシェル・スクリプトの作成
以下にあげる基本的なステップと推奨事項は、Linuxで実行する多くのクライアント / サーバー・アプリケーション に適用することができます。
- スクリプトを実行するための前提条件およびメイン・シーケンスを文書化する
- アクションを論理グループに分割する
- 一般的な使用のシナリオに基づいて、実行シーケンスを開発する
- それぞれのシェル・スクリプトに対して、コメントおよび指示を用意する
- ベースラインを作成するため、初期バックアップをとる
- 入力パラメーターおよび環境変数をチェックする
- "usage" に関するフィードバックを提供する
- 「無音」の実行モードを提供する
- エラーが起こったときに、スクリプトを終了する機能を1つ提供する
- 可能であれば、単純なタスクを確実に行うような機能を提供する
- 各スクリプトの出力を取り込みながら、同時に作成中の出力を表示する
- 各スクリプト内で、それぞれの行コマンドの戻りコードを取り込む
- 失敗したトランザクションの数をカウントする
- 出力ファイルにおいて、エラー・メッセージは、判別しやすいように強調表示する
- 可能であれば、「オンザフライ」でファイルを生成する
- スクリプト実行の進行についてフィードバックを提供する
- スクリプト実行状況の要約を提供する
- 解釈しやすい、出力ファイルを提供する
- 可能であれば、クリーンアップ・スクリプト、およびベースラインに戻る方法を提供する
以下に、それぞれの推奨事項の詳細を、bashシェル・スクリプトの例とともに示します。このスクリプトをダウンロードするには、この記事の後半の参考文献のセクションをご覧ください。
1. スクリプトを実行するための前提条件およびメイン・シーケンスを文書化する
機能テストの主な内容を、できれば一見して内容を推察できるような、すなわち自己記述的なタイトル (README-testing.txtなど) を 付けて、単一の文書として文書化することが重要です。主な内容とは、前提条件、サーバーとクライアントの設定、後に続くスクリプトの全体的 (あるいは詳細) なシーケンス、スクリプトが正常に実行されたか失敗したのかをチェックする方法、クリーンアップの実行方法、およびテストを再スタートする方法などです。
2. アクションを論理グループに分割する
実行するアクションの数が少ない場合は、すべてのアクションを単一のシェル・スクリプトに入れることができます。
しかし、アクションの数が多い場合は、いくつかの論理セットにグループ分けすることをお勧めします。たとえば、サーバー・アクションをあるファイルにまとめ、クライアント・アクションを別のファイルにまとめるなどします。こうすると、より細分性の高いテストを行い、これらのテスト・ケースを維持することができます。
3. 一般的な使用法のシナリオに基づいて、実行シーケンスを開発する
アクションのグループ分けを決定したら、アクションを一般的な使用法のシナリオに従った順序で実行すること を検討します。この目的は、実際のエンド・ユーザーの状況をシミュレートすることです。検討する際は、原則として最もよく起動される機能の約80%がテストできる、使用ケースの20%に 重点を置くようにしてください。
たとえば、アプリケーションが特定のシーケンスの3つのテスト・グループを必要とするとしましょう。それぞれのテスト・グループは、1つファイルの中に入れて、自己記述的なファイル名を持たせ (可能であれば)、またシーケンスにおけるそれぞれのファイルの順序を示すための番号を付けることもできます。たとえば:
1. fvt-setup-1: To perform initial setup.
2. fvt-server-2: To perform server commands.
3. fvt-client-3: To perform client commands.
4. fvt-cleanup: To cleanup the temporary files,
in order to prepare for the repetition
of the above test cases. |
4. それぞれのシェル・スクリプトに対して、コメントおよび指示を用意する
各シェル・スクリプトのヘッダー部分に適切なコメントと指示を書くことは、良いコーディングの実践方法です。こうすれば、別のテスト担当者がこれらのスクリプトの実行を担当しても、そのテスト担当者は前提条件や警告 だけでなく、各スクリプトにおいてどこまでテストが終了しているかも明確に理解することができます。
以下に示す例は、bashスクリプト例 "test-bucket-1" からのものです。
#!/bin/bash
#
# Name: test-bucket-1
#
# Purpose:
# Performs the test-bucket number 1 for Product X.
# (Actually, this is a sample shell script,
# which invokes some system commands
# to illustrate how to construct a Bash script)
#
# Notes:
# 1) The environment variable TEST_VAR must be set
# (as an example).
# 2) To invoke this shell script and redirect standard
# output and standard error to a file (such as
# test-bucket-1.out) do the following (the -s flag
# is "silent mode" to avoid prompts to the user):
#
# ./test-bucket-1 -s 2>&1 | tee test-bucket-1.out
#
# Return codes:
# 0 = All commands were successful
# 1 = At least one command failed, see the output file
# and search for the keyword "ERROR".
#
########################################################
|
5. ベースラインを作成するため、初期バックアップをとる
機能テストは、何回か行う必要がある場合があります。1回目の実行では、大抵の場合スクリプトまたはプロシージャーに何らかのエラーが見つかります。そのため、サーバー環境をスクラッチから作成し直すことで長時間を無駄にすることを避けるため (とくに データベースが関係している場合)、テストを開始する直前にバックアップをとることをお勧めします。
機能テスト・ケースを実行し終わった後に、バックアップからサーバーを復元して、次のテストに備えることができます。
6. 入力パラメーターおよび環境変数をチェックする
入力パラメーターを検証して、必要な環境変数が適切に設定されているかチェックすることをお勧めします。問題がある場合は、その問題の原因およびその修正方法を表示してから、スクリプトを終了します。
通常このスクリプトを実行するテスト担当者は、変数が正しくない場合にはスクリプトが起動されたらすぐに 終了してほしいと思うことでしょう。スクリプトの実行を長時間待たされ、その結果として変数が適切に設定されていないことを知らされて 喜ぶ人はいません。
# --------------------------------------------
# Main routine for performing the test bucket
# --------------------------------------------
CALLER=`basename $0` # The Caller name
SILENT="no" # User wants prompts
let "errorCounter = 0"
# ----------------------------------
# Handle keyword parameters (flags).
# ----------------------------------
# For more sophisticated usage of getopt in Linux,
# see the samples file: /usr/lib/getopt/parse.bash
TEMP=`getopt hs $*`
if [ $? != 0 ]
then
echo "$CALLER: Unknown flag(s)"
usage
fi
# Note quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
while true do
case "$1" in
-h) usage "HELP"; shift;; # Help requested
-s) SILENT="yes"; shift;; # Prompt not needed
--) shift ; break ;; *) echo "Internal error!" ; exit 1 ;;
esac
done
# ------------------------------------------------
# The following environment variables must be set
# ------------------------------------------------
if [ -z "$TEST_VAR" ]
then
echo "Environment variable TEST_VAR is not set."
usage
fi
|
このスクリプトに関しては、以下の点に注意してください。:
- ステートメント、
CALLER=`basename $0` は、実行中のスクリプトの名前を知りたい場合に使用します。こうすれば、スクリプト内にスクリプト名をハードコーディングする必要がありません。また、スクリプトをコピーする際に、新しくできたスクリプトを適合させるのが簡単になります。
- ステートメント、
TEMP=`getopt hs $*` は、スクリプトが起動された時に、入力引数 (ヘルプの場合 -h、無音モードの場合 -sなど) を知りたい場合に使用します。
- ステートメント、
[ -z "$X" ] およびecho "The environment variable X is not set." およびusage は、ストリングがヌル (-z) かどうかをテストするために使用します。ヌルの場合は、ストリング設定されていないことを示すechoステートメントを実行して、後で説明する "usage" 関数を起動します。
- スクリプトがフラグを使用しない場合は、変数 "$#" を使用できます。この変数は、スクリプトに渡される 引数の数を戻します。
7."usage" に関するフィードバックを提供する
スクリプトの使用方法を説明する以下のような "usage" ステートメントの使用をお勧めします。
# ----------------------------
# Subroutine to echo the usage
# ----------------------------
usage()
{
echo "USAGE: $CALLER [-h] [-s]"
echo "WHERE: -h = help "
echo " -s = silent (no prompts)"
echo "PREREQUISITES:"
echo "* The environment variable TEST_VAR must be set,"
echo "* such as: "
echo " export TEST_VAR=1"
echo "$CALLER: exiting now with rc=1."
exit 1
}
|
この "usage" ステートメントは、"-h" フラグを使用してスクリプトを起動したときに、呼び出すことができます。たとえば以下のとおりです。
./test-bucket-1 -h
8. 「無音」の実行モードを提供する
スクリプトには、2つの実行モードを設定することができます。
- "verbose" モード (これをデフォルトにすることをお勧めします) では、ユーザーに値を入力するか、または 単にEnterキーを押して作業を継続するようにプロンプトが出されます。
- "silent" モードでは、データ入力のプロンプトは出されません。
以下の抜粋例は、スクリプトを無音モードで実行するための呼び出しフラグ "-s" の処理方法を示しています。
# -------------------------------------------------
# Everything seems OK, prompt for confirmation
# -------------------------------------------------
if [ "$SILENT" = "yes" ]
then
RESPONSE="y"
else
echo "The $CALLER will be performed."
echo "Do you wish to proceed [y or n]? "
read RESPONSE # Wait for response
[ -z "$RESPONSE" ] && RESPONSE="n"
fi
case "$RESPONSE" in
[yY]|[yY][eE]|[yY][eE][sS])
;;
*)
echo "$CALLER terminated with rc=1."
exit 1
;;
esac
|
9. エラーが起こったときに、スクリプトを終了する機能を1つ提供する
クリティカルなエラーが発生した時に、スクリプトの実行を終了するための関数を1つ用意することをお勧めします。この関数は、クリティカルなエラーが発生した場合にどうするべきかについての、追加の説明を提供することができます。
# ----------------------------------
# Subroutine to terminate abnormally
# ----------------------------------
terminate()
{
echo "The execution of $CALLER was not successful."
echo "$CALLER terminated, exiting now with rc=1."
dateTest=`date`
echo "End of testing at: $dateTest"
echo ""
exit 1
}
|
10. 可能であれば、単純なタスクを確実に行うような機能を提供する
たとえば、以下のような長い行コマンドを発行しないでもよいやり方を考えます。
# --------------------------------------------------
echo ""
echo "Creating Access lists..."
# --------------------------------------------------
Access -create -component Development -login ted -authority plead -verbose
if [ $? -ne 0 ]
then
echo "ERROR found in Access -create -component Development -login ted -authority plead"
let "errorCounter = errorCounter + 1"
fi
Access -create -component Development -login pat -authority general -verbose
if [ $? -ne 0 ]
then
echo "ERROR found in Access -create -component Development -login pat -authority general"
let "errorCounter = errorCounter + 1"
fi
Access -create -component Development -login jim -authority general -verbose
if [ $? -ne 0 ]
then
echo "ERROR found in Access -create -component Development -login jim -authority general"
let "errorCounter = errorCounter + 1"
fi
|
この場合は、以下のような関数を作成することができます。この関数もまた、戻りコードを処理し、必要であればエラー・カウンターを増やすことができます。
CreateAccess()
{
Access -create -component $1 -login $2 -authority $3 -verbose
if [ $? -ne 0 ]
then
echo "ERROR found in Access -create -component $1 -login $2 -authority $3"
let "errorCounter = errorCounter + 1"
fi
}
|
... そして、読み込みおよび拡張が容易に行える方法でこの関数を呼び出します。
# -------------------------------------------
echo ""
echo "Creating Access lists..."
# -------------------------------------------
CreateAccess Development ted projectlead
CreateAccess Development pat general
CreateAccess Development jim general
|
11. 各スクリプトの出力を取り込み、同時に作成中の出力を表示する
スクリプトが自動的に出力をファイルに送信しない場合は、スクリプトが作成する出力を取り込むために bashシェルの機能を活用することができます。たとえば次の例です。
./test-bucket-1-s2>&1| tee test-bucket-1.out |
上記のコマンドを分析してみましょう。
- "2>&1" コマンド:
"2>&1" を使用して、標準エラーを標準出力にリダイレクトします。ストリング "2>&1" は、すべてのエラーが標準出力に送信されることを示します。つまり、UNIX/Linux ファイルID 2は標準エラーで、ファイルID 1は標準出力です。このストリングを使用しない場合は、正常な場合のメッセージのみが取り込まれ、エラー・メッセージは取り込まれません。
- パイプ "|" および "tee" コマンド:
UNIX/Linuxプロセスと単純なプラミング (plumbing) の概念には、大きな類似性があります。ここでは、パイプラインへの入力が対象スクリプトからの出力となるようなパイプラインを作成することにします。次に決定することは、そのパイプラインの出力をどう処理するかです。この例では、先ほどの例で "test-bucket-1.out" と命名した出力ファイルに出力を取り込むことにします。
しかし、出力を取り込むだけでなく、スクリプトの実行中に作成される出力の表示もしたいとします。そのために、ここでは2つの作業の同時進行を可能にする "tee" (T型パイプ) を付加しています。つまり、出力をあるファイルに配置して、同時に出力を画面に表示するのです。プラミングとの類似性は以下のように表されます。
プロセス --> T --> 出力ファイル | V 画面
もし、出力の取り込みのみが必要でそれを画面に表示する必要がない場合は、以下のような余分な プラミングは省略することができます。
./test-bucket-1 -s 2>&1 > test-bucket-1.out
このケースにおいてプラミングとの類似性は以下のようになります。:
プロセス --> 出力ファイル
12. 各スクリプト内で、それぞれの行コマンドの戻りコードを取り込む
機能テストの成功または失敗を判別する1つの方法は、失敗した行コマンドの数をカウントすることです。つまり、戻りコードが0以外の行コマンドをカウントします。変数 "$?" で、最近呼び出されたコマンドの戻りコードを入手することができます。以下の例では、この変数は "ls" コマンド 実行の戻りコードを示しています。
# -------------------------------------------
# The commands are called in a subroutine
# so that return code can be
# checked for possible errors.
# -------------------------------------------
ListFile()
{
echo "ls -al $1"
ls -al $1
if [ $? -ne 0 ]
then
echo "ERROR found in: ls -al $1"
let "errorCounter = errorCounter + 1"
fi
}
|
13. 失敗したトランザクションの数をトレースし記録する
機能テストの成功または失敗を判別する1つの方法は、0以外の値を戻す行コマンドの数をカウントすることです。しかし、筆者が実際に作業する際には、整数ではなく自分のbashシェル・スクリプトのストリングのみを 扱うのが習慣になっています。筆者が参考にしていたマニュアルは、整数の使用法についてあまり明確に説明がされて いませんでした。ですから、ここでは整数の使用法とさらにエラー (行コマンドの失敗) のカウント方法について少し詳しく述べて みたいと思います。
まず、カウンター変数を以下のように初期化します。
次に、行コマンドを発行し、$? 変数を使用して戻りコードを取り込みます。戻りコードが0でない場合は、カウンターを1つ増やします (青い太字のステートメントをご覧ください) 。
ListFile()
{
echo "ls -al $1"
ls -al $1
if [ $? -ne 0 ]
then
echo "ERROR found in: ls -al $1"
let "errorCounter = errorCounter + 1"
fi
}
|
ところで、整変数は "echo" を使用すると他の変数として表示することができます。
14. 出力ファイルで、エラー・メッセージを、判別しやすいように強調表示する
エラー (または、失敗したトランザクション) が発生した場合は、エラー・カウンターを増やすだけでなく、エラーがあったことを示す内容をプリントすることをお勧めします。できれば、文字ストリングにERRORまたはそれに似たようなサブストリング (青字のステートメントを参照) を加えるのが望ましいでしょう。それによって、テスト担当者が出力ファイルからエラーを容易に見つけることが できます。出力ファイルが大きい場合もあるので、エラーを素早く見つけることは重要です。
ListFile()
{
echo "ls -al $1"
ls -al $1
if [ $? -ne 0 ]
then
echo "ERROR found in: ls -al $1"
let "errorCounter = errorCounter + 1"
fi
}
|
15. 可能であれば、「オンザフライ」でファイルを作成する
アプリケーションが使用するファイルを扱うことが必要な場合があります。既存のファイルを使用することもできますし、スクリプトにステートメントを追加してファイルを作成することも できます。必要なファイルが大きい場合は、別のエンティティーとして保持することをお勧めします。ファイルが小さくかつ内容が単純であったり関係のないもの (重要なのはその内容にかかわらず テキスト・ファイルであることです) である場合は、これらの一時ファイルを「オンザフライ」で作成すること ができます。
以下のコードは、一時ファイルを「オンザフライ」で作成する方法を示しています。
cd $HOME/fvt
echo "Creating file softtar.c"
echo "Subject: This is softtar.c" > softtar.c
echo "This is line 2 of the file" >> softtar.c
|
最初のechoステートメントは、単一の > を使用して、新しいファイルの作成を指示しています。2つめのechoステートメントは、2重の >> を使用して、既存のファイルの末尾にデータを付加しています。既存のファイルがない場合は、新規のファイルが作成されます。
16. スクリプト実行の進行状況についてフィードバックを提供する
スクリプトには、実行の論理的な進行状況を示すためのechoステートメントを含めることをお勧めします。出力の目的を素早く認識するために何か付け加えることができます。
スクリプトの実行に数秒以上の時間がかかりそうな場合は、スクリプト実行の始めと終わりに 日付をプリントすることができます。これによって、経過時間を計算することができます。
スクリプト例では、進行状況を表示するためのechoステートメントが示されています。
# --------------------------------------------
echo "Subject: Product X, FVT testing"
dateTest=`date`
echo "Begin testing at: $dateTest"
echo ""
echo "Testcase: $CALLER"
echo ""
# --------------------------------------------
# --------------------------------------------
echo ""
echo "Listing files..."
# --------------------------------------------
# The following file should be listed:
ListFile $HOME/.profile
...
# --------------------------------------------
echo ""
echo "Creating file 1"
# --------------------------------------------
|
17. スクリプト実行の要約を提供する
エラーまたは、失敗したトランザクションをカウントする際には、エラーがあったかどうかを示すことをお勧めします。これにより、テスト担当者が出力ファイルの末尾を見てエラーがあったかどうかを迅速に確かめられるようなります。
以下のスクリプト例で、コード・ステートメントは以下のような実行の要約を提供しています。
# --------------
# Exit
# --------------
if [ $errorCounter -ne 0 ]
then
echo ""
echo "*** $errorCounter ERRORS found during ***"
echo "*** the execution of this test case. ***"
terminate
else
echo ""
echo "*** Yeah! No errors were found during ***"
echo "*** the execution of this test case. Yeah! ***"
fi
echo ""
echo "$CALLER complete."
echo ""
dateTest=`date`
echo "End of testing at: $dateTest"
echo ""
exit 0
# end of file
|
18. 解釈しやすい、出力ファイルを提供します。
スクリプトによって生成された実際の出力に、何かキーとなる情報を含めておくと大変便利です。これによってテスト担当者は、表示されているファイルが適切なものでありかつ最新のもであるかどうかを簡単に判断することができます。最新かどうかが分かるように、日付スタンプを加えておくことが重要です。また、要約レポートがあると、エラーがあったかどうかを判断するために役立ちます。エラーがあれば、テスト担当者は、ERRORなどの特定のキーワードで検索して、失敗した個々のトランザクションを判別できます。
以下に省略した出力例を示します。
Subject: CMVC 2.3.1, FVT testing, Common, Part 1
Begin testing at: Tue Apr 18 12:50:55 EDT 2000
Database: DB2
Family: cmpc3db2
Testcase: fvt-common-1
Creating Users...
User pat was created successfully.
...
Well done! No errors were found during the
execution of this test case :)
fvt-common-1 complete.
End of testing at: Tue Apr 18 12:56:33 EDT 2000
|
エラーが発生した際の出力ファイルの末尾は以下のようになります。
ERROR found in Report -view DefectView
*** 1 ERRORS found during the execution of this test case. ***
The populate action for the CMVC family was not successful.
Recreating the family may be necessary before
running fvt-client-3 again, that is, you must use 'rmdb',
'rmfamily', 'mkfamily' and 'mkdb -d',
then issue: fvt-common-1 and optionally, fvt-server-2.
fvt-client-3 terminated, exiting now with rc=1.
End of testing at: Wed Jan 24 17:06:06 EST 2001
|
19. 可能であれば、クリーンアップ・スクリプト、およびベースラインに戻る方法を提供する
テスト・スクリプトが一時ファイルを作成することがあるので、これらの一時ファイルを削除する スクリプトを用意しておくことをお勧めします。こうすることにより、テスト担当者がすべての一時ファイルを削除しなかったり、さらに悪い場合には一時的ではない必要な ファイルを削除してしまう、というようなミスを避けることができます。
機能テスト用のbashシェル・スクリプトの実行
このセクションでは、機能テスト用のbashシェル・スクリプトの実行方法について説明します。皆さんが、これまでのセクションのすべてのステップを実行済みであると前提とします。
必須の環境変数の設定
以下の環境変数を .profileで指定するか、あるいは必要に応じて手動で指定します。この変数は、スクリプト内の処理の方法を説明するために使用されます。環境変数を必要とする検査は、スクリプトを実行する前に定義しなければなりません。
bashシェル・スクリプトを適切なディレクトリーにコピーする
bashシェル・スクリプトとその関連ファイルは、機能テストを実施するユーザーIDのディレクトリー構造に コピーする必要があります。
- アカウントにログインします。ホーム・ディレクトリーに入るはずです。このディレクトリーを /home/testerとします。
- テスト・ケース用にディレクトリーを作成します :
mkdir fvt
- bashシェル・スクリプトとその関連ファイルをコピーします。ZIPファイル (参考文献を参照) を入手して、それを $HOMEの下に配置します。それから、以下のようにして解凍します:
unzip trfvtbash.zip
- これらのファイルを実行するために、適切なファイル許可を変更します:
chmod u+x *
- 名前を変更して、ファイルの接尾部を除去します:
mv test-bucket-1.bash test-bucket-1
スクリプトの実行
スクリプトを実行するには、以下を行ってください
- テスト担当者のユーザーIDにログインします。
- スクリプトをコピーした先のディレクトリーに移動します:
cd $HOME/fvt
- $HOME/fvtから次のスクリプトを実行します:
./test-bucket-1 -s 2>&1 | tee test-bucket-1.out
- 出力ファイル "test-bucket-1.out" の末尾を見て、要約レポートの結果を確認します。
参考文献
著者について  | |  | Angel Riveraは、VisualAge TeamConnectionの技術サポート・チームのアドバイザリー・ソフトウェア・エンジニアで、現在はチームのリーダーとし活躍しています。オースチンのテキサス大学で電気工学の理学修士号を、そして メキシコのInstituto Tecnologico y de Estudios Superiores de Monterreyで電気システム工学の理学士号 を取得しています。Angelは1989年にIBMに入社しました。連絡先は、rivera@us.ibm.com
この記事の執筆にあたり、AngelはWebSphere技術サポートのLee Perlovに謝意を表しています。 |
記事の評価
|