2013年4月21日日曜日

JaCoCO Maven Pluginでテストケースのカバレッジもとる

JaCoCoというJavaのカバレッジライブラリを調べています。

テストコードを書いて確認。EclipseのプラグインであるEclEMMAは内部でJaCoCoを使っています。
とりあえずオールグリーンです。


カバレッジが100%ではないですが、ここでは問題にしません。#ほんとはこれを調べてたんですが。
ちゃんとテストコードのカバレッジもとれてます。


次にMaven Pluginです。使ったバージョンは、0.6.3-SNAPSHOT。
HTML、XML、CSVでレポートが出力されます。HTMLのレポートを開いたものです。テストコードのカバレッジが無いです。


調べていくと、prepare-agentゴールでデータを作って、reportゴールでレポート化しています。
prepare-agentゴールでは、JavaAgentを使ってデータを取っています。この辺はたぶんEclEMMAも一緒のはず。
実際、HTMLレポートのSessionsのリンクをたどると、実行時のデータがすべて出てます。


ここを見るとちゃんとテストコードも通ってます。ということは、データは取れているけどレポートできてない、EclEMMAで出てるという事は、Maven Pluginで出ていないですね。


で、いろいろとpomをいじってみましたが駄目だったのでソースをみることに。
https://github.com/two-pack/jacoco/blob/master/jacoco-maven-plugin/src/org/jacoco/maven/BundleCreator.java
 public IBundleCoverage createBundle(
   final ExecutionDataStore executionDataStore) throws IOException {
  final CoverageBuilder builder = new CoverageBuilder();
  final Analyzer analyzer = new Analyzer(executionDataStore, builder);
  final File classesDir = new File(this.project.getBuild()
    .getOutputDirectory());

  @SuppressWarnings("unchecked")
  final List<File> filesToAnalyze = FileUtils.getFiles(classesDir,
    fileFilter.getIncludes(), fileFilter.getExcludes());

  for (final File file : filesToAnalyze) {
   analyzer.analyzeAll(file);
  }

  return builder.getBundle(this.project.getName());
 }

classesDirがgetOutputDirectory()になってます。target/classesだけみたい。。。
ということは、target/test-classesも入れれば良いってことかな?
 @SuppressWarnings("unchecked")
 public IBundleCoverage createBundle(
   final ExecutionDataStore executionDataStore) throws IOException {
  final CoverageBuilder builder = new CoverageBuilder();
  final Analyzer analyzer = new Analyzer(executionDataStore, builder);
  final File classesDir = new File(this.project.getBuild()
    .getOutputDirectory());
  final File testClassesDir = new File(this.project.getBuild()
    .getTestOutputDirectory());

  final List filesToAnalyze = FileUtils.getFiles(classesDir,
    fileFilter.getIncludes(), fileFilter.getExcludes());
  filesToAnalyze.addAll(FileUtils.getFiles(testClassesDir,
    fileFilter.getIncludes(), fileFilter.getExcludes()));

  for (final File file : filesToAnalyze) {
   analyzer.analyzeAll(file);
  }

  return builder.getBundle(this.project.getName());
 }

ということでビルドして入れてレポート出した見た結果がこちら。ちゃんと出ました。


テストコードのカバレッジってデフォルトで出た方が、テストが思いがけず通ってない場合が見れていいと思うんですが、どうですかね?
フラグとテスト作ってリクエストしてみようかな。

2013年4月9日火曜日

長岡 IT開発者 勉強会(NDS) 第31回勉強会に参加しました。 #nds31

長岡 IT開発者 勉強会(NDS) 第31回勉強会に参加しました。
NDS自体初めての参加でしたが、とても楽しむ事ができました。
http://nagaoka.techtalk.jp/no31

テーマは「はじめての~」。初心者向けのテーマでなにか話して!ということでした。
以下、発表のまとめというよりも、気になったところの備忘録。発表順です。
スライドなど最新は上のページでまとまってます。

第31回勉強会 アジェンダ(@civicさん)

はじめてNDSに参加されたかたも多かったとの事で、@civicさんからNDSについての説明がありました。
誰にでも発表の場を提供します!、というのは、新潟において貴重な場ではないかと感じました。

はじめてのChrome App (@civicさん)

Chromeアプリでデバイスなどの低いレイヤーのAPIもあるということでした。
実際にUDPでメッセージを受けるデモをされてました。
bluetoothとかもあったので、今後何かやっていたいと思いました。

はじめてのmac用ビューアアプリ(@piras4さん)

最近はMBAべったりなのにXCode使ってみたこともない、、、、という私にはぴったりでした。
こんな風にするんだ、という感じでした。

はじめてのテスト技法 (@two_pack)

NDSの実施ポリシーが非常にいいね!と思い、NDS初参加でしたが私も発表してきました。
http://nagaoka.techtalk.jp/Home
中身はテスト技法の話はしておらずw、「ソフトウェアテスト」に触れるきっかけになれればいいなということで書きました。
初めてSlideshareにも載せてみました。100viewいくとメールが来るんですねw

はじめてのPerl(のモダン?な環境構築) (@hajyajoさん)

Perlの開発環境についてでした。システムPerlという言葉を初めて知りましたorz
開発環境用にバージョンを入れ替えるとか、ライブラリを指定のところに入れるとか、rvmみたいのか、と聞いていました。
IDEもあるようですw

はじめてのWindowsストアアプリ (@AILightさん)

生MVPだよ!生Surfaceだよ!と思ってたのは秘密ですw
ちょうど前の日に8のアプリを少し見たのもあって、非常に興味深かったです。
8がないのが痛いですが、やってみたいなあ、と思いました。

新潟スピリチュアル専科・または恋は言ってみりゃアウトプット (@neko_gata_sさん)

いきなりCoooolな音楽から始まりました!
新人教育で使いたいと思うし、うんうんとうなる、非常に良い話でした。楽しいって大事ですよね!
waveずたずたは原曲が気になるレベルのアウトプットでした。
プロセスさんには、ぜひpullRequestできるように読み込んでみたいです。

はじめてのメタプログラミング (@neko_gata_sさん)

メタな話でした。
ちょうどRubyGemのrequireでそんなのみたところだったので、Perlだとあんな感じでできるのか、と聞いてました。

わたしのRubyとの出会い (@kasacchifulさん)

@kasacchifulさんは、すわにいでもご一緒している方なんですが、ruby長いんだなあ、と今更w
Redmineのプラグインみてるのに、しっかり勉強してない、ってところを痛感したので、お勧めの本を読もうと思います。

懇親会

開発者で飲むってこういうのだよね、って感じですごく楽しかったです。
ただ、ちょっと楽しみ過ぎたのが玉にきずでした。。。 #おかげでこれ書くのも遅くなってる。。。

その他
そして、名刺のgithubとbitbucketのURLが逆になっているという@neko_gata_sさんからの指摘に愕然としましたorz
テストの話しておいて、このバグ。。。。

2013年3月30日土曜日

Redmine XLS Export PluginのRedmine 2.3.0対応

XLS Export PluginのRedmine 2.3.0対応を行って0.2.1.t2にバージョンをあげました。
https://github.com/two-pack/redmine_xls_export/tree/0.2.1.t2


2.3.0での問題

Redmineのapplication.cssが変わったため、管理者のプラグイン設定画面の表示が崩れていました。以下のチケットです。
https://github.com/two-pack/redmine_xls_export/issues/19


対処

XLS Export Pluginは、作者のVitaly Klimovが同じく作成しているPlugin views revisionsを使ってRedmineのバージョン違いに対応しているため、今回も使ってみました。
revフォルダの下にバージョンごとのファイルを作成すれば、インストール手順にある以下のRakeコマンドでRedmineのバージョンに合わせたファイルが使われます。
$ rake redmine:plugins:process_version_change RAILS_ENV=production

実際に行った対応は、このコミットで概略は以下の通りです。

  1. もともとのCSSである assets/stylesheets/xls_export.css をrev/assets/stylesheets/1.3.0-xls_export.css として移動。
  2. redmine_xls_export/rev/assets/stylesheets/2.3.0-xls_export.cssとして、Redmine 2.3.0用のCSSを作成。


Redmine XLS Export Pluginの競合

年頭にXLS Export Pluginのフォーラムで、チケットリストのQUICKリンクでzipファイルが正しく作られないという問題が報告されてました。

調べてみると拡張子はzipなんだけど、実際にはxlsファイルだと判明。。。
ソースを追っていくと以下の部分が該当箇所。
export_nameには出力するファイル名と拡張子が入っています。issues_xlsはxlsファイルの内容で、zipの場合はこの後にrubyzipを使ってzipファイルにする処理があります。
export_name[1] == 'zip'はtrueだけど、Zip::ZipOutputStream::write_bufferがfalseの場合は、現象が起きるルートになります。
issues_xls=issues_to_xls2(@issues, @project, @query, @settings)
    return issues_xls unless export_name[1] == 'zip' && defined?(Zip::ZipOutputStream::write_buffer)


Zip::ZipOutputStream::write_bufferがない?

rubyzipをrequireしているのにZip::ZipOutputStream::write_bufferがないってどういうこと?
いろいろ調べていくと、Redmine DMSF Pluginが入っている場合に起きる事が判明。
DMSF Pluginではrubyzipではなくzipをbundlerでインストールしていました。

これによってrubyzipとzipの両方がgemに入っている状態になります。
どちらのプラグインも、以下のようにしてロードしています。
require 'zip/zip'

しかし、ロードパスの優先順位の関係でzipのほうがrubyzipよりも先に見つかるので、zipがrequireされます。
そして、zipにはZip::ZipOutputStream::write_bufferが含まれていない、というのが原因でした。


調査と対応

XLS Export Pluginだけrubyzipを呼び出す方法とかないのかな?と、いろいろ調べてみたんですが分からず。
rubyzipとzipでdiffをとるとrubyzipのほうが包含しているようにみえたので、DMSF Pluginにrubyzip使ってもらえないかとPull-Requestしたら取り込んでもらえました。
いっけんらくちゃくw

#でも、そもそもZip::ZipOutputStream::write_bufferが無い場合にzip拡張子で出すという処理自体にも問題があると思うんですが。。。


2013年3月24日日曜日

JaSST'13 Niigataに参加してきました。

2013/3/15に行われたJaSST'13 Niigataに参加してきました。
今回は参加している勉強会「すわにい」の成果発表で登壇もしてきました。
http://www.jasst.jp/symposium/jasst13niigata.html

遅くなりましたが、気づきのあった事を書いてみます。
ちゃんと内容理解できているか不安ですが。。。

2013/4/10追記
JaSSTのサイトにレポートがアップされました。スライドも見れます!
http://www.jasst.jp/symposium/jasst13niigata/report.html

基調講演
「仕様ベースのソフトウェアテストを上手に進めるには
~明文化された要求仕様に対して漏れなくテストするための観点とは~」
大西 建児さん

仕様ベースのテストで何がむずかしいか、を4つの視点からむずかしさを説明されました。「むずかしさ」を整理するポイントを教えて頂けたと感じました。

  • ISTQBとは、というお話から。JSTQBのFoundation Levelを持っているはずの私ですが、成果発表の資料の用語からしてISTQBの用語に沿ってない・・・・と焦りました(ーー; もう一度シラバスを読もうと思います。
  • 自然言語による仕様記述でのあいまいさ。言葉を尽くして表現しなくてはならない。
  • 情報が絡み合ってごちゃごちゃしている状態。情報の整理が必要。
  • 複数のテストアイテムに対するテスト条件がいっぱいあり整理できない。
  • テスト条件とは、テストアイテムについてテストしなくてはならないこと。
  • 現在ではユースケースが膨大になるのが当たり前。どこまで保証するか範囲を決めることになる。
  • 製品、サービスの領域に関する知識は持っている必要がある。すべてを知っている必要があるということではなく、テスト対象が目的を果たせるか確認するのに必要なことは知っている必要がある。

演習付きチュートリアル
「マインドマップを用いたテスト要求分析・設計エクササイズ」
鈴木 三紀夫さん

テスト分析、設計でマインドマップを活用する、、、の前にテストケースに至までのテストプロセスのお話がありました。また、講演自体をマインドマップで各自書いていく、という流れ。私は結局A3で2枚ぶんになりました。

  • テストレベルごとにテストプロセスがあり、そのプロセスがフェーズ(時間の流れ)の中に当てはまっていく。これははじめて絵をみてなるほどと思いました。
  • 視座、視野、視点を意識してテスト観点を列挙していく。
  • 演習ではある機能に対してどんなテストが必要かをマインドマップで考えるというものでした。
  • 情報交換会や打ち上げなどで他の人のものを聞いてみると、自分で気づかなかったところも多々あり。なるほどなあ、というところも多く、視野が狭いなあと感じました。

事例発表
「新潟ソフトウェア開発勉強会『すわにい』の活動」
すわにい

すわにいで行ったテスト設計の成果発表を行いました。あとは、参加者募集!の宣伝w
独自のテスト設計アプローチとして、利用者の安全をキーワードにアバター抽出とそれぞれに対するフローからポイントを洗い出す、というものでした。
ご講評として、大きく2点コメントを頂きました。アプローチ、手法という観点ではなるほどなあ、と感じ入りました。

  • アプローチでの結果の再現性。同じ事をやったときに同じ結果につながるのか?ということ。アバターの抽出、フローの作成ともに「気づき」を促すもので、再現性があるかというと乏しいと確かに感じました。
  • フローである事の意義。前述の通り「気づき」を促すものとしてフローではなくマインドマップなども同じような効果が得られそうです。


去年は参加できずのJaSST Niigataでしたが、一昨年同様多くの気づきを得ることができました。
やはり本やネットだけでなく、実際に聞いて話してみると感じる事があります。それを実際の開発にもつなげていけたらと思いました。
#オフィシャルのレポートが上がったらリンクを追記しようと思います。

2013年3月7日木曜日

Redmine 2.2.x でのXLS Export Pluginの動作確認

ぐぐったら、動いている風な記載がありました。


なんで、自分の追加したところの確認をしました。
特に問題なく動いていました。

環境


  • OS
    Mac OS X 10.7.5
  • 環境
    Redmine version 2.2.3.stable
    Ruby version 1.8.7 (universal-darwin11.0)
    Rails version 3.2.12
    Environment production
    Database adapter SQLite
  • Redmine plugins
    redmine_plugin_views_revisions 0.0.1
    redmine_xls_export 0.2.1.t1

2013年1月9日水曜日

[Spring] Autowiredアノテーションを使っているクラスのユニットテスト

ちょっと確認のために試してみました。ソースは以下。
https://bitbucket.org/twopack/jsonrest/commits/e5353d883dffe31f99948a977b938c69
試したかったのは、 @Autowired でインジェクションしているクラスをJUnitで動かすにはどうするかです。

上記のソースで autoPerson を @Autowired してます。
決めうちでアクセスすると、autoPerson にアクセスして Micheal を返すようにしています。

テスト側で対応を行わない場合、テストを実行すると autoPerson で NullPointerException になります。JUnitで実行時には、 @Autowired でインジェクションが行われていないことが原因です。
対策のポイントは、以下のサイトを参照しました。



@Autowiredアノテーションを有効にする

1つ目のポイントは、JUnitのテストに @RunWith(SpringJUnit4ClassRunner.class) と @ContextConfiguration を記載して、 Spring の TestRunner で動くようにします。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class HomeControllerTest {
....
}

@ContextConfiguration を記載すると、クラスパス上の テストクラス名-context.xml を読み込んで設定します。
この中で、インジェクションするbeanを設定します。
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  <beans:bean name="Person" class="jp.gr.java_conf.twopack.sample.jsonrest.Person"></beans:bean>
  </beans:beans>

テスト対象クラスのインスタンス化

1つ目のポイントでOK・・・かと思いきや、状況は変わりませんでした。
以下のようにアプリケーションコンテキストのメソッドを使ってテスト対象をインスタンス化する必要がありました。
@Autowired
ApplicationContext ctx;
 
HomeController sut;
  
@Before
public void setup() {
  sut = ctx.getAutowireCapableBeanFactory().createBean(HomeController.class);
}


ここまでで、テストも通るようになりました。

RedmineプラグインをGitHub Actionsでテストする

Redmine Advent Calendar 2019 の Qiita で書きました。追っかけで もう一つ 。 Travis-CIで行っていたRedmineプラグインのCIを、GitHub Actionsに変更したものです。 GitHub Actionsをやってみようという...