gdbでリモートデバッグ
コンパイルしたマシンと別のマシンで動作しているプログラムをgdbデバッグする方法のメモ。
プログラムを動かすサーバにgdbserverをインストールする。インストールはyumから出来る。
# yum install gdb-gdbserver
接続を受け付けるIPアドレスとポートを引数で指定し、起動済みプロセスのPIDを指定してgdbserverを起動。
# gdbserver 10.0.0.1:54321 --attach 16781
コンパイルマシンの方でgdbを立ち上げ、target remoteで、gdbserver起動時に指定したIPアドレス、ポート番号を指定してアタッチする。
$ gdb prog (gdb) target remote 10.0.0.1:54321 Remote debugging using 10.0.0.1:54321 [New Thread 16781] Malformed packet(b) (missing colon): re:2; Packet: 'T0505:786a8ebf;04:406a8ebf;08:2454e400;thread:418d;core:2;'
gdbとgdbserverのバージョンが違うとダメらしい。
gdbのバージョンが6.8-27.el5だったので、そのバージョンのgdbserverをbuildする。
$ tar xjf gdb-6.8a.tar.bz2 $ cd gdb-6.8/ /tmp/gdb-6.8 $ cd gdb/gdbserver /tmp/gdb-6.8/gdb/gdbserver $ ./configure --prefix=/usr/local $ make $ sudo make install
今回の動作環境では、コンパイルしたサーバとプログラム実行するサーバで、ライブラリのバージョンが違うためうまく動かなかった。
ライブラリバージョンが合えば使えるはず。。
gdbserver: error initializing thread_db library: version mismatch between libthread_db and libpthread
なお、gdbでのデバッグ終了時はdetachで終了すること。 exitで終了すると、リモートサーバ側のプロセスが終了してしまうので注意要。
参考:
BuildingCrossGDBandGDBserver - GDB Wiki
GDB/GDBserverによるクロスターゲットのリモートデバッグ 3ページ | SourceForge.JP Magazine
PythonからOracle接続
PythonでOracle接続してデータ検索する方法のメモ。
環境
OS | Python | Oracle Client |
---|---|---|
CentOS 6.4 | 3.3.0 | 11.2.0.3.0 |
インストール
Oracleへの接続ライブラとして、cx_Oracleをインストールする。
Oracleクライアントは既にインストールされている環境を使用したので、そちらのインストールは省略。(多分以下の4つのrpmをインストールした環境のはず)
- oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
- oracle-instantclient11.2-precomp-11.2.0.3.0-1.x86_64.rpm
- oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
- oracle-instantclient11.2-sqlplus-11.2.0.3.0-1.x86_64.rpm
まずは、cx_Oracleインストールに必要なpython3-develのインストール。
$ sudo yum install python3-devel 読み込んだプラグイン:fastestmirror, refresh-packagekit, security インストール処理の設定をしています Loading mirror speeds from cached hostfile * PUIAS_6_computational: puias.math.ias.edu * base: ftp.iij.ad.jp * centosplus: centos.mirror.secureax.com * epel: epel.mirror.srv.co.ge * extras: centos.mirror.secureax.com * updates: ftp.iij.ad.jp 依存性の解決をしています --> トランザクションの確認を実行しています。 ---> Package python3-devel.x86_64 0:3.3.0-1.puias6 will be インストール --> 依存性解決を終了しました。 依存性を解決しました =================================================================================================================== パッケージ アーキテクチャ バージョン リポジトリー 容量 =================================================================================================================== インストールしています: python3-devel x86_64 3.3.0-1.puias6 PUIAS_6_computational 169 k トランザクションの要約 =================================================================================================================== インストール 1 パッケージ 総ダウンロード容量: 169 k インストール済み容量: 532 k これでいいですか? [y/N]y パッケージをダウンロードしています: python3-devel-3.3.0-1.puias6.x86_64.rpm | 169 kB 00:01 rpm_check_debug を実行しています トランザクションのテストを実行しています トランザクションのテストを成功しました トランザクションを実行しています インストールしています : python3-devel-3.3.0-1.puias6.x86_64 1/1 Verifying : python3-devel-3.3.0-1.puias6.x86_64 1/1 インストール: python3-devel.x86_64 0:3.3.0-1.puias6 完了しました!
続いて、cx_Oracleのインストール。
$ echo $ORACLE_HOME /usr/lib/oracle/11.2/client64 $ sudo ln -s /usr/include/oracle/11.2/client64 $ORACLE_HOME/include $ su # echo /usr/lib/oracle/11.2/client64/lib >> /etc/ld.so.conf.d/oracle.conf $ sudo ldconfig $ pip install cx_Oracle (途中略) Successfully installed cx-Oracle Cleaning up...
環境設定(クライアント環境)
自分の環境のOracle周りの設定。 LD_LIBRARY_PATHの設定は必須。 他は関係ない設定もあると思うけどメモがてら載せとく。
export ORACLE_HOME=/usr/lib/oracle/11.2/client64 TNS_ADMIN=$ORACLE_HOME/network/admin export TNS_ADMIN export NLS_LANG=Japanese_Japan.AL32UTF8 NLS_DATE_FORMAT='YYYYMMDDHH24MISS' export NLS_DATE_FORMAT NLS_TIMESTAMP_FORMAT='YYYYMMDDHH24MISS.FF3' export NLS_TIMESTAMP_FORMAT export PATH=$PATH:$HOME/bin:$ORACLE_HOME/bin export LD_LIBRARY_PATH=.:$ORACLE_HOME/lib:/lib:/usr/lib:/usr/local/lib
データ取得
テーブルからデータを取得して表示してみた。
$ python3 Python 3.3.0 (default, Feb 12 2013, 17:01:04) [GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import cx_Oracle >>> conn=cx_Oracle.connect('scott','tiger','xx.xx.xx.xx/tns_service_name') >>> cur=conn.cursor() >>> sql="select * from scott.db_tbl where rownum<20" >>> cur.execute(sql) <cx_Oracle.Cursor on <cx_Oracle.Connection to scott@xx.xx.xx.xx/tns_service_name>> >>> rows=cur.fetchmany(10) >>> print(len(rows)) 10 >>> print(cur.rowcount) 10 >>> for row in rows: ... print(row) ... (tupleデータ10行出力) >>> rows=cur.fetchmany(10) >>> print(len(rows)) 9 >>> print(cur.rowcount) 19 >>> for row in rows: ... print(row) ... (tupleデータ9行出力) >>> rows=cur.fetchmany(10) >>> print(len(rows)) 0 >>> print(cur.rowcount) 19 >>> cur.close() >>> conn.close()
この内容を元にして、テーブルレコード全件をCSVファイルに出力するPythonスクリプト作ってみた。
#!/usr/bin/python3 import cx_Oracle import sys import csv from itertools import chain argvs = sys.argv argc = len(argvs) if argc != 2: print('Usage: %s TableName' % argvs[0]) quit() table_name = argvs[1].upper() file_name = table_name + '_data.csv' with cx_Oracle.connect('scott','tiger','xx.xx.xx.xx/tns_service_name') as conn: # テーブルの列名取得 column_name_sql = 'select column_name from user_tab_columns where table_name = :tbl' cur_columns = conn.cursor() cur_columns.execute(column_name_sql, tbl=table_name) columns = cur_columns.fetchall() cur_columns.close() columns = tuple(chain.from_iterable(columns)) # テーブルのレコード全件取得 data_sql = 'select * from %s' % table_name cur_data = conn.cursor() cur_data.execute(data_sql) with open(file_name, 'w') as f: csv_writer = csv.writer(f) csv_writer.writerow(columns) while 1: rows = cur_data.fetchmany(50) if len(rows) == 0: break csv_writer.writerows(rows) cur_data.close()
参考:
pythonからOracleに接続するための拡張モジュール、cx_Oracleの基本的な使い方 at nkjmkzk.net
UbuntuでPythonからcx_Oracleモジュールを使ってOracle Database 11gに接続する - 偏った言語信者の垂れ流し
Cursor Object — cx_Oracle 5.1.3 documentation
ソフトウェアテスト勉強会 ~PistMasterを使い倒す!~に行ってきました
2014/11/28のソフトウェアテスト勉強会のレポート。
今回の勉強会は、組み合わせテストの項目を簡単に作成するPictMasterの勉強。
インストール
ここからPistMasterをダウンロード。
PictMaster プロジェクト日本語トップページ - OSDN
ダウンロードしたファイルにユーザーズマニュアルが含まれてるので、その手順に従ってインストールする。
実践
基本
フォント4種類と、それぞれのフォントで太字、斜体、下線、影付きの有無を組み合わせるテスト項目。
パラメータ名と、それぞれのパラメータの値を','区切りで入力する。
(日本語入力でカンマを入力するのはちょっと面倒だけどそこは我慢)
実行ボタンを押すと、a.xlsというファイル名で、以下が出力される。
各項目について、2項目の組み合わせ(フォント-太文字、太文字-斜体字など)のパターン全てが出力されている。
組み合わせ項目数を変えたい場合は、環境設定->組み合わせるパラメータ数 を変更する。
実行ボタン押下すると、3項目の組み合わせ(フォント-太文字-斜体字など)全てが出力される。
なお、環境設定でシードの値を変えると、別の組み合わせパターンが出力される。 (シードの値を変えなければ抽出される項目は常に同じ。)
同値分割
複数の値がテストとして同じ意味を持つ場合、同値分割によりテスト項目数を減らす事が出来る。 同値は、各値を'|'で区切って指定する。
出力した結果。フォント4種類の値を同値としているため、テスト項目が減っている。
排他指定と結果表
Webからの入力項目の試験。 名前、メールアドレスは、入力がなければエラーとする。
名前:未入力とメールアドレス:未入力を組み合わせた試験を行うと、エラー発生時、どちらの未入力が原因でエラーになったのか分からなくなるため、各試験パターンについて、未入力とするのは、名前とメールアドレスのどちらかのみとする必要がある。 この場合、組み合わせてはいけない値は、'~'から始まるように記載する。
また、結果表を使用し、名前未入力、メールアドレス未入力の場合の結果もテスト結果として出力してみる。 結果表は「環境設定」->「結果表を使用」にチェックを入れる事により使える。
実行結果。 名前=未入力とメールアドレス=未入力が組み合わさったパターンは出力されない。 また、各試験パターンについて、結果も出力される。
特定条件でのみ許容するパターン
ラーメン注文のパターン試験。ただし、以下の条件あり。
- 紅しょうがは、とんこつの場合のみ可。
- すりおろしニンニクは、とんこつ以外の場合のみ可。
- とんこつの場合、麺の茹で方はバリカタ、カタのみ可。
この場合、制約表により組み合わせの条件を指定し、制約条件になる方("if(トッピング==紅しょうが) then スープ=とんこつ"のif文になる方)に色を付ける。
色は何でもよい。
制約表で「~以外」という指定を行う場合、#から始まる値を指定する。今回は「#とんこつ」で「とんこつスープ以外」を指定している。
*(ワイルドカード)も使用できる。ワイルドカードは部分一致する条件の指定に使用する。
なお、残念ながらワイルドカードのみの指定はできなかった。
実行結果。
- トッピング=紅しょうがはスープ=とんこつとの組み合わせのみ出力されている
- トッピング=すりおろしニンニクはスープ≠とんこつの組み合わせのみ出力されている
- スープ=とんこつの茹で方はカタ、バリカタのみ出力されている
「ありえない組み合わせを試験パターンから除く」ための指定なので、「該当のパターンを指定されたらエラーにする」ような試験では使用しないよう注意。
応用
問題内容。
問題には記載がないが、ブラウザのパターンも組み合わせに入れる。
自分が作成したもの。
他の参加者が作成したシンプルな回答。
自分が作成したものと比べると、こっちの方がすっきりして見やすい。レビューもしやすそう。
PictMasterのマニュアルを見ると、他にも色々機能があるっぽい。
今まで組み合わせテスト作る時は、マトリクスで組み合わせを検討してたけど、こちらの方が簡単だし、パターンの抜けがないので便利。 次の組み合わせテストの項目作成で使ってみよう。
UX仙台 デザイナーが大事にしていること に行ってきました
2014/11/15のUX仙台のレポート。
チームで協業するための、共有のしかた (フジタジュンコさん)
過去
デザインチームが話を聞いた時点で開発期間はもう決まってたりする。
前工程で遅延が発生してても、〆切は変わらない。
デザイナーはその短い期間内で徹夜してでも頑張って終わらせる。
なのに、
「この通りに作ってくれればいいから」と言ってたのに、出来上がったら
「何か違うんだよねぇ。。」と言われたり、
全部作り終わって、テストに入ろうという時になって、
「偉い人がダメって言うから直して」と言われたりする。
死にたい...
なぜこうなる?
「この通りに作ってくれればいいから」の何が悪いかというと、意図を全く伝えていない。
そうなるとアウトプットもいいものが出来ない。指示が明確でないものをデザイナーは表現できない。
お客様に検証するための指標がない。
指標がないので、偉い人が「これじゃダメだよ」と言った事をそのままデザイナーに返す。
どうすれば?
全体を見ることが必要。
Webを作るといった時、製作者はWebだけ考えて良い物を作ろうとしてしまう。
ユーザは「何かをしたい」「何か欲しい」ためにWebを触る。
ユーザに価値を提供する媒体としてWebがあり、ユーザはWebではなく「Webを通して得られる体験」にお金を払う。
全体の流れの中にWebがあることを理解する必要がある。
ユーザに届ける価値が一番大事。
ユーザが「お金を払っても良い」と思える価値は何か?
チームでコンテクストを共有する。
全体でコンテキストを共有しないと最高のものを提供することはできない。
全体を見て協業するためにやってきたこと
インセプションデッキ
良かった点
- コンパクトなので、共有がすばやくできる。
- キャッチフレーズを作ると、Webサイトでそのまま使える。
- ミーティング1~2回で作れる
悪かった点
- どの程度具体的にすればよいのかが難しい。
- 大きいプロジェクトだと、内容がざっくりすぎて、何回も作る羽目になった。
大規模なプロジェクトでは難しいが、中規模、小規模のプロジェクトでは有用。
インセプションデッキを使用することで、ユーザが何を求めているか?
我々のサービスがどうアプローチ出来るかを共有する事が出来る。
ビジネスモデルキャンバス
良かった点
- チーム外の活動(営業、マーケットの動き、エバンジェリストの活動等)を洗い出す事ができた。
- 顧客にもたらす価値を共有できた。
- コミュニケーションのポリシーまで決められた。
悪かった点
- 時間がかかる。(以前のプロジェクトでは1週間くらいかかった)
デザインコンセプトを作る時には有効。
他にカスタマージャーニーマップも参考になる。
ペーパープロトタイピング
UI設計書の前にペーパーでプロトタイピングしたもの。
UIするデザイナーとのやりとりに使っていた。
社内でテスターの人を呼んでペーパーで使い勝手をテストしてもらう。
良かった点
- ペーパーで一旦テストしているので、後で「この画面使えない」という事はなかった。
- テストとデザインを別立てで走らせられる。デザイナーを待たせないで済む。
悪かった点
- 工作に時間がかかる。
- 学習コストが高い。
- 紙は動かないので、インタラクション設計を別にする必要がある。
画面遷移がそれほど多くないものであれば、紙に書いたものをデザイナーに渡すだけで、デザイナーは割とやれる。
気を付けている事
全体を見て共有する事によるメリット
プロジェクトが始まった時点ではみんな「よいもの」を作りたいと思っている。
職歴、立場等で、「よいもの」がずれてくる。
「ユーザにとって」よいものを作るために上記の手法は有用。
デザインワークをスムーズにする、共有のしかた (井上亜津奈さん)
デザインはふわっとしたモノととらわれがち。
なぜこのデザインにしたか、デザイナーは常に答えを用意しておかなければいけない。
クライアントは説明の方にお金を払っている。
デザインの目的は課題の把握と解決。
デザインで何ができるかを考えて、具体的な方法を提示する。
主観やセンスで片付けられるものではない。
デザインの現場でよくある事
でも、お客さんは悪くない。当たり前の事。
お客さんに分かりやすいものを提示して誘導するのもデザイナーの仕事。
明確なイメージを一緒に探らなければ迷路に迷い込んでしまう。
まず、ビジネスやサービスの目的を理解すること。
デザインに出来ない事も理解しておくこと。
「検索で常に上位に来る」とかはデザインでは出来ない。
トーン&マナーを作る
トーンとは、企業やサービスがもってる「らしさ」の事。
トーン(概念)をルール化したものをトーン&マナーという。
トーン&マナーを作るときはターゲットが大切。
デザインの前に表現の方向性の共有を行う。これでデザインが楽になる。
ヒアリングでは世界観を表すものだったら何でも(雑誌、サイト、ブランド等)いいので聞く。
ユーザのヒアリングに有効な手法
言語マトリクス
ユーザヒアリングの中で出てきた抽象的なワードを拾って言語マトリクスを作成し、どのあたりを狙うかを考える。
競合の会社がマトリクス上どのあたりに位置するかをポイントし、そのあたりは外すという事も出来る。
お客さんも参加しやすいというメリットがある。
カラーリング
こんなキーワードで、こんなターゲットで、こんな組み合わせはどうでしょう? と提案する。
カラーは世界を決めてしまうものなので大切。
イメージボード
世界観を表す画像を集めたスクラップブックのようなもの。
手間はかかる。
お客さんとイメージ共有を手っ取り早くするために使用する。
サンプルサイト
見えるものに引っ張られてしまうという弊害がある。
見せたサイトと全く同じものを作ると思われたり、イメージではなくガワの話に終始する危険性がある。
使えるかはお客さんに依る。
ワークショップ
2チームに分かれてのデザインワークショップ。
自分のチームは、ずんだPRのためのWebサイトリニューアル企画検討。
(課題内容書いた紙を持ち帰るの忘れた orz)
ワークショップの内容
- 依頼内容の確認。
- 依頼内容を元にお客様にヒアリング。(ヒアリングシート無くしたので写真なし。)
- ヒアリングした内容から、企画検討。
- プレゼンのボードを作成し、お客様(相手チーム)にプレゼン。
企画検討
良かったところ
- 企画検討のとき、アイデアを各自が発言しながら付箋に書いて貼っていくのは良かった。(誰か一人が記載するより早い。人の発言を聞きながら自分の手を動かせる)
- 企画検討で、対象の情報をググって、アイデアのヒントになる情報を探すのは有効。(「ずんだは仙台七夕あたりからお盆までが繁忙期」という情報から、七夕祭りとファッションショーを関連付ける案が出た。)
- いまいちだな、と思ってもとりあえず出してみる。他の人がそのアイデアを膨らませてくれるかも。
- アイデア出しのとき、「否定しない」事は大事。人のアイデアで「いまいちだな」と思っても、「このアイデアの活かせそうなところは。。」という方向で考えて、アイデアを発展させることが出来た。
悪かったところ
- お客さんへのヒアリングが難しかった。抽象的なイメージを聞くためにどんな質問したら良いか分からなかった。今ブロク見返して、言語マトリクスとか使ってみても良かったと思ったり。
自分のチームで作成したプレゼンボード。
作成した後に思ったのが、「ユーザの発言全てに応えようとはしなくて良い」事。
お客様の色々な立場の人が、それぞれの立場から意見を出してきたら、その中には相反する要望、実現出来ない要望、単なる思いつきの要望も入ってるはず。
なので、要望全てに応えようとするのではなく、要望をヒントに方向性を決めて、その方向性に沿って提案をする事が大事。
自分も含めて、プログラマーは言われたことは全て実現しないといけないという考えになりがちなので、この視点は意識しないといけない。
デザインにもアジャイルの手法が有効な事が分かったのは面白かった。
- 作者: Jonathan Rasmusson,西村直人,角谷信太郎,近藤修平,角掛拓未
- 出版社/メーカー: オーム社
- 発売日: 2011/07/16
- メディア: 単行本(ソフトカバー)
- 購入: 42人 クリック: 1,991回
- この商品を含むブログ (249件) を見る
IntelliJでスネークケースとキャメルケースの切替
IntelliJで、変数のsnake_case⇔CamelCaseの切替(Eclipseだとctrl+alt+kで出来る)をどうやってやればよいか調べたのでメモ。
Plugin入れないとダメらしい。
試した環境は、IntelliJ IDEA 12.1.6、Windows7 Professional。
導入手順
- JetBrains Plugin Repository :: CamelCaseをインストールしてIntelliJ再起動。
- 切替する単語にカーソルのせて、Shift+Alt+uで切替。押す度に切り替わる。
is_readable という単語を切り替えてみると、
- IS_READABLE
- IsReadable
- isReadable
- is_readable
というように切り替わる。
Pythonのデフォルト引数にハマった
Python初心者がハマるポイントにしっかりハマってしまったので記録残しとく。
Pythonの関数引数にはデフォルト値が指定できる。
時刻指定する関数で、引数省略時は現在時刻を取得する関数を作ろうとした。
import time def tim(t=time.time()): print(t) if __name__ == "__main__": tim() time.sleep(1.25) tim() time.sleep(1.4) tim()
が、このtim関数を実行すると、同じ時間しか取得されない。
C:\>python.exe time_func_test.py 1414077198.46061 1414077198.46061 1414077198.46061
このデフォルト引数の値はモジュール評価時に決まるようで、一度関数を実行すると、後は決まった値が使用され続けるらしい。
上記の関数ではやってないけど、デフォルト引数にリストなどの可変オブジェクトを渡して、処理内でリストを更新すると、次の関数コール時は更新したリストが渡されてしまう。
元々やりたかった処理は、以下のような処理で実現した。
import time def tim(t=None): if t is None: t=time.time() print(t) if __name__ == "__main__": tim() time.sleep(1.25) tim() time.sleep(1.4) tim()
実行結果。毎回値が変わるようになったのでやりたいことは出来たっぽい。
C:\>python.exe time_func_test.py 1414078025.345443 1414078026.595514 1414078027.997595
ExpectedExeptionを使ってみる
JavaでExceptionが発生する事を検証するテストは以下のように書く事が出来る。
@Test(expected = IllegalArgumentException.class) public void Exceptionの検証() { throw new IllegalArgumentException("このメッセージは検証できない"); }
ただ、このテストケースでは、意図したExceptionが発生する事は検証できるが、そのExceptionの内容の検証を行う事が出来ない。
Exceptionの検証にExpectedExceptionクラスが使えるという情報を貰ったので使い方を確認。
使い方
サンプル
import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.hamcrest.Matchers.endsWith; public class ExpectedExceptionTest { // @Ruleを付加するフィールドはpublicフィールドとする @Rule public ExpectedException expected = ExpectedException.none(); @Test public void ExpectedExceptionを使ったException検証() { // 検証する内容を設定 expected.expect(IllegalArgumentException.class); expected.expectMessage("sample"); // 部分一致検証 expected.expectMessage(endsWith("exception")); // Exceptionが発生する処理を実行 new SampleClass(null); } static class SampleClass { SampleClass(String str) { if ( str == null ) { throw new IllegalArgumentException("sample exception"); } } } }
このコードで、Exception#getMessage()の内容を検証する事が出来る。
なお、ExpectedException#expectMessage(String)メソッドは部分一致の検証である事に注意。
JUnit実践入門にも載ってた。
JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)
- 作者: 渡辺修司
- 出版社/メーカー: 技術評論社
- 発売日: 2012/11/21
- メディア: 単行本(ソフトカバー)
- 購入: 14人 クリック: 273回
- この商品を含むブログ (67件) を見る