メディアフォース 開発者ブログ

株式会社メディアフォースの開発者による非公式ブログです。

テスティングフレームワークを試す

おはようございます。 メディアフォースの齊藤です。

毎年恒例で16日はアプレッソさんのAdvent Calendarに参加させていただいております。 qiita.com

ということで今回は DataSpider Servista 4.1 で追加された、地味に使えると評判のテスティングフレームワークを試してみます。

テスティングフレームワークとは

アプレッソのサイトで公開されているヘルプによると テスティングフレームワーク

テスティングフレームワークとは、「DataSpider Servistaで開発したスクリプトのテストをどのように記述して、実行し、検証するか」という仕組みを支援する一連の機能群と、それらを効果的に使用するためのガイドラインの総称です。

とあります。

単独の機能を表しているわけではなく、その言葉とおりにフレームワークとして定義されているようです。

機能面では、

  • テスト用スクリプトを作成できる
  • テスト用スクリプトを一括実行できる
  • テストに利用できる検証用アイコンが用意されている
  • テスト後にテストレポーティングが自動生成される

とのことで、JavaJUnitのようなイメージになりそうです。

当社のようなSIerでは、作成したプロジェクトを納品するにあたってテスト仕様書やテスト結果報告書は必ず作るので自動生成されてくれるのは中々良さそうです。

早速試していきます。

とりあえず適当なCSVを読んでフィルタリング、フォーマッティングしてExcelで出力する処理でも作ってみましょう。 f:id:mf_sol_eai:20171216151639p:plain

ん?

f:id:mf_sol_eai:20171216152003p:plain

早くも出てきたぞ・・・ このタイミングで作れるということは、テストを先に作るテストファーストでもいけそうですね。 せっかく気がついたのでテストファーストで試してみましょう。

テストファーストの場合、 あるべき仕様 としてテストを定義します。

今回は次のようなCSVファイルから山形県出身だけ抽出して連番を振り直したファイルを作成する処理を想定します。


連番,氏名,氏名(カタカナ),性別,電話番号,メールアドレス,生年月日,出身地 1,丹羽羽菜,タンバハナ,女,0238039536,atamba@xwseri.ol,1979/04/29,岐阜県 2,三好千夏,ミヨシチナツ,女,0892703515,umiyoshi@mwkhbhyh.cv,1988/01/19,山形県 3,山川美羽,ヤマカワミウ,女,05906205,miu_yamakawa@nkbzvbvk.pak,1965/03/31,石川県 4,三村利治,ミムラトシハル,男,0991816393,toshiharu08482@lbomk.lw,1978/05/06,愛知県 5,陳一也,チンカズヤ,男,023924877,kazuya212@hwkgv.ih,1971/11/10,沖縄県 6,勝又文乃,カツマタアヤノ,女,0184439746,ayano85398@memr.idf,1964/09/15,山形県 7,青野柚衣,アオノユイ,女,0539608685,yui702@ldeku.mykzg.ado,1977/01/17,山形県 8,羽鳥修一,ハトリシュウイチ,男,0760818209,shuuichi_hatori@anxgfcs.yfb,1962/06/13,栃木県 9,大嶋優花,オオシマユカ,女,0930535292,yuka83358@wmcxlnuuh.nt,1962/11/25,茨城県

10,関口友吉,セキグチトモヨシ,男,0556578828,isekiguchi@typslyh.cl,1967/12/06,山形県

処理の期待値としては以下のようになります。


連番,氏名,氏名(カタカナ),性別,電話番号,メールアドレス,生年月日,出身地 1,三好千夏,ミヨシチナツ,女,0892703515,umiyoshi@mwkhbhyh.cv,1988/01/19,山形県 2,勝又文乃,カツマタアヤノ,女,0184439746,ayano85398@memr.idf,1964/09/15,山形県 3,青野柚衣,アオノユイ,女,0539608685,yui702@ldeku.mykzg.ado,1977/01/17,山形県

4,関口友吉,セキグチトモヨシ,男,0556578828,isekiguchi@typslyh.cl,1967/12/06,山形県

とりあえずメインのスクリプトを作ります。

f:id:mf_sol_eai:20171216160007p:plain

f:id:mf_sol_eai:20171216160550p:plain

テストから作るのでスクリプトの中身はカラのままです。

テストスクリプトを開いて、テストしたスクリプトをドラッグ・アンド・ドロップします。 f:id:mf_sol_eai:20171216160802p:plain

続いて、スクリプトから出力されたファイルを読みます。

f:id:mf_sol_eai:20171216162839p:plain

f:id:mf_sol_eai:20171216164351p:plain

続いてデータの検証をするアイコンを配置します。

f:id:mf_sol_eai:20171216164523p:plain

「テーブルモデル比較」を使います。

f:id:mf_sol_eai:20171216165205p:plain

f:id:mf_sol_eai:20171216165308p:plain

フローをつなげてテストスクリプトは完成

f:id:mf_sol_eai:20171216170238p:plain

テストスクリプトができましたので、スクリプトを作っていきます。

f:id:mf_sol_eai:20171216171224p:plain f:id:mf_sol_eai:20171216170653p:plain

さて、テストスクリプトを実行してみましょう

f:id:mf_sol_eai:20171216171333p:plain

エラーになってしまいました。 「連番」の1行目が期待値と違うようです。

出力されたデータをみるとなるほど、連番の振り直しをしていませんでした。

f:id:mf_sol_eai:20171216171503p:plain

ということで、「出力ノード番号」を使って連番を振り直します。

f:id:mf_sol_eai:20171216171650p:plain

改めて実行しましょう。

f:id:mf_sol_eai:20171216171817p:plain

成功です!

テストを先に作るテストファーストにも向いていて開発効率があがりそうですね。 今回は簡単なテストでしたが、次回は(あるのか!?)もう少し複雑なテストを作ってレポートまで出力してみたいと思います。

DataSpiderを使ってCSVに存在しないレコードを削除する

アプレッソさんのコミュニティを眺めてたら面白そうな質問があったのでちょっと試してみました。

dstn.appresso.com

やりたいこととしては、CSVファイルを読んで、CSVファイル中に存在するデータは残し存在しないデータは削除したいということのようです。

存在するデータは削除だったら非常に簡単なんですが、「存在しない」というのはデータを全部読んでみないとわからないのでちょっと難しいですね。

ということで、フラグを立てるパターンを簡単に実装してみます。

まず、テーブルの状態はこんな感じ。

f:id:mf_sol_eai:20170629112608p:plain 元データ提供は なんちゃって個人情報 から拝借。

MAILカラムがPrimaryKeyとなるイメージです。

つづいて入力データです。

f:id:mf_sol_eai:20170629122356p:plain

メールアドレスのみが載ってます。 ここに載っているレコードは削除せず、それ以外のレコードを全部削除したい、ということですね。

まずは全レコードに削除用フラグを立てておきます。 Oracleの場合は真偽値を表す型がないので、numeric(1) で代用しました。

UPDATE “SAMPLE1” SET ON_DELETE = 1

削除フラグに「1」を入れておきます。DataSpiderでは「更新系SQL実行処理」を使います。

f:id:mf_sol_eai:20170629122715p:plain

これを実行すると ON_DELETE に「1」が入った状態になりました。

f:id:mf_sol_eai:20170629122821p:plain

次にCSVファイルを読んで、存在するレコードは削除フラグを消します。 今回は削除フラグが「1」のデータは削除、「0」のデータは残すことにしたので、今度は削除フラグを「0」で更新していきます。

CSV読み取りはアドレスだけ

f:id:mf_sol_eai:20170629122957p:plain

更新系SQL実行処理で ON_DELETE = 0 します。

f:id:mf_sol_eai:20170629123043p:plain

更新系SQL実行処理の場合、「?{var}」とSQL文に書くことでMapperから値をセットできるようになります。

Mapperの画面は単純にCSVの「アドレス」をSQLの変数「mail」に入れるだけです。

f:id:mf_sol_eai:20170629123208p:plain

これを実行すると、CSVにある3レコードだけがON_DELETE = 0 になりました。

f:id:mf_sol_eai:20170629123301p:plain

最後に ON_DELETE = 1 を条件としてDELETE文を発行します。

DELETE FROM “SAMPLE1” WHERE ON_DELETE = 1

実行すると、CSVにある3レコードだけ残して他のレコードはすべて削除されました。

f:id:mf_sol_eai:20170629123448p:plain

それぞれをつなげるとこういうスクリプトになります。

f:id:mf_sol_eai:20170629123639p:plain

DataSpider DevConn ハッカソン開催!

新年明けましておめでとうございます。*1

当社とお付き合いも長く、当ブログでも名前がよく挙がりますアプレッソさん とこの度、3月にハッカソンを開催する運びになりました。

その名も

DataSpider DevCon Hackathon

dstn.connpass.com

DataSpider の新製品である DataSpider Cloud がリリースされたことを記念してDataSpider をお使いの方も、検討されている方も、初めて聞いた方も、DataSpider Cloudに触っていただきつつ各種APIと連携し、未来の何かを作ろうという企画です。

DataSpiderを触ったことがない方、当社現役エンジニアがサポートいたしますのでご安心ください。

connpassには載ってませんが優秀な作品には各社から賞品が出るとか出ないとか。

是非この機会に当社のエンジニアとDataSpider Cloudを使った連携システムを開発してみていただければと思います。

*1:あけて一発目なので。。。

Pepperくん秘書化計画 ~スケジュール編~

Zenfone 3につづいて Zenbook 3 を発売日に購入したメディアフォース齊藤です。
Zenfone 3 Laserを購入しようか迷ってます。

本記事はアプレッソ Advent Calendar 2016 の16日目の記事です。
qiita.com

去年も書かせていただいてますが、偶然にも 同じく16日でした。

スクリプト開発時に気をつけるべき3つのポイント - Appresso Engineer Blog

毎年12月16日は齊藤の日として広めて参りたいと思います。

Pepperくん秘書化計画とは

さて、Pepperくん秘書化計画についてご説明しましょう。

みんなだいすき顔面蒼白のPepperくんですが、説明係だったり案内係だったりとめんどくさい客来客対応として使われるケースが多いように思います。

Pepperくんを個人で購入される方はあまり多くはないと思いますが、なかなかに値が張ります
せっかくなので自分のために使いたい!ということでPepperくんには秘書として存分に働いてもらおう計画です。

構成図

f:id:mf_sol_eai:20161215110923p:plain

  1. Pepperくんに教えを乞う
  2. PepperくんがDataSpider Cloud(以下、DSC)にHTTPリクエスト飛ばす
  3. DSCがGoogle API経由でスケジュールを取得
  4. DSCでスケジュールをセリフ状のテキストに整形し、レスポンスボディで返す
  5. Pepperくんが受け取ったテキストを喋る

やろうと思えばPepper -> Google APIの直接でも出来ると思うんですが、GoogleのOAuth2認証やテキスト整形がめんどくさかったので簡単にできそうなDataSpiderを利用しました。
ちなみにDSCはまだリリースされていないので、DSC想定で普通のDataSpiderをEC2に置いてある感じです。

Google APIを取得する

DataSpiderによるGoogle API連携についてはこの記事を参考にしてます。
DataSpider RESTアダプタを使ってGoogleカレンダーの予定を取得する。 - Qiita

記事からちょっと変えた点

  • 認証情報の「APIを呼び出す場所」をその他のUIに変更してます。

f:id:mf_sol_eai:20161215112414p:plain

この場合、リダイレクトURLは不要ですが、http://localhost:7700 を指定しておきます。

また、最近 Google アカウントは二段階認証を導入しましたが、検証時点では二段階認証があると認証のレスポンスが受け取れなかったので無効にしてます。

DataSpider側のアプリをつくる

github.com

DSC_GoogleCalendar.zip に DataSpider プロジェクトを置いてあります。

  1. OAuth認証のグローバルリソースを作成しておく。
  2. 変数のcalendarIdに取得したいカレンダーIDを入れておく。カレンダーIDについてはここでは説明しないのでググってください。
  3. 実行すると、returnText にセリフ状のテキストが入ります。
  4. サービス登録し、HTTPトリガーを作成する。HTTPトリガーでreturnTextをレスポンスボディに含める設定にします。
  5. HTTPトリガーの設定が完了したら、ブラウザからHTTPトリガーにアクセスする。
  6. ブラウザにテキストが表示されたらOKです。

スクリプトの流れ

f:id:mf_sol_eai:20161215130754p:plain

  1. Google APIでカレンダーを取得する
  2. Mapperを使ってサマリ、開始日時、終了日時を取得する。
  3. 一旦CSVに吐いておく
  4. 吐いたCSVを読んでPepper用テキストに整形する。

Pepperアプリ

Pepperアプリの開発にはChoregrapheを使っています。
Pepperは「今日のスケジュール」といったワードに反応してスケジュールを教えて欲しいところです。

  • Choregrapheプロジェクト全体像

f:id:mf_sol_eai:20161215131049p:plain

ということでChoregrapheプロジェクトはPepper_DSC.zipに置いてます。

プロジェクトの構成

  1. Speech Reco. で「今日;明日;ありがとう」を登録しておきます。「今日」と「明日」でそれぞれのスケジュールを通知し、「ありがとう」で終了します。
  2. TextEditの「DataSpiderのURL」には先程ブラウザで確認したURLを設定しておきます。
  3. HTTP Getはこちらの記事を参考にしていますが、変えた部分があるのでコード全文載せておきます。
class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        #put initialization code here
        pass

    def onUnload(self):
        #put clean-up code here
        pass

    def onInput_onStart(self, url):
        from HTMLParser import HTMLParser
        import urllib2, contextlib

        class ContentParser(HTMLParser):
            def __init__(self):
                HTMLParser.__init__(self)
                self.inscript = False
                self.inbody = False
                self.text = ""

            def handle_starttag(self, tag, attrs):
                if tag == "body":
                    self.inbody = True
                if tag == "script":
                    self.inscript = True

            def handle_endtag(self, tag):
                if tag == "body":
                    self.inbody = False
                if tag == "script":
                    self.inscript = False

            def handle_data(self, data):
                if self.inbody and not self.inscript:
                    self.text = self.text + data

        try:
            timeout = int(self.getParameter("Timeout"))
            self.logger.info("Loading... %s" % url)
            response = urllib2.urlopen(url)
            text = response.read()

            self.logger.info("Loaded: %s" % text)
            self.onStopped(text)
        except urllib2.URLError, message:
            self.logger.warn("Failed to open: %s, message=%s" % (url, message))
            self.onFailed(message)

コードはやっつけですみません。。。

デモ

中々おもしろい感じにできたんじゃないでしょうか

あいだにDataSpiderを経由することで実装がやや難しい認証周りが比較的簡単に実装できたり、DeepLearningに学習用データも一緒に登録したりもできたりするのでPepper単体で完結できるものでも挟んでおくと色々はかどりそうですね :D

第二回社内LT大会リンク

先日、社内ハッカソン&LT大会を開催しました。

mf-sol-eai.hatenablog.com

せっかくなのでLT資料をあげたいと打診してみたところあげてもいいよ!って方がいたので、Slideshareのリンク集にしました。

LTリンク

AngularJS 触ってみたファーストインプレッションについて

www.slideshare.net

おすすめのサービスエリア・パーキングエリア(関東編)

www.slideshare.net

茨城県民魂の叫び

www.slideshare.net

プリン体はほどほどに

www.slideshare.net

愛車をJavaモデリングした人(謎)

www.slideshare.net

prezi初挑戦
Bootstrap入門

www.slideshare.net

第三回社内ハッカソン開催しました。そしてLT大会へ

全国のSIerの皆様いかがお過ごしでしょうか。

f:id:mf_sol_eai:20161204234236j:plain

ハッカソン

当社では定期的にハッカソンを実施しており、先月11/25に第三回ハッカソンを開催しました。 多少前後はあるものの、6人*6チームの36人程度に規模になります。

キックオフとチーミングタイム f:id:mf_sol_eai:20161204235908j:plain 衝立の向こう側ではえらい人達も見学に...

テーマは「身近な業務改善」ということで、各々様々な業務に対して改善を提案していました。 SIerと言えばプログラミングをしてるイメージがあると思いますが当社では、配属先によって事業内容が大きく変わることもあり、プログラミングに拘らずチームによって得意な手法を用いてました。

筆者がPepperにハマっていることもあって当チームはPepperにフォーカスした開発を。 f:id:mf_sol_eai:20161204234832j:plain

テーマ:Pepper秘書 f:id:mf_sol_eai:20161204235656j:plain

1年目の若手から10年超のベテランまで一緒に作業中 f:id:mf_sol_eai:20161205000510j:plain

そして今回は、ファイル転送ソフトHULFTで有名なセゾン情報システムズ様からもご参加いただいたこともあり、DataMagicを活用していたチームもありました。

また、さらに来年入社予定の内定者も数名お招きしてハッカソンを体感してもらいました。 研究などでプログラミングをした経験がある方もいましたが、現役の開発者と開発する経験は良い刺激になったんじゃないでしょうか。

はい、そして終わったあとは懇親会です。 f:id:mf_sol_eai:20161204234343j:plain チームの皆との乾杯はまた格別ですね。

そしてLT大会へ...

今回はハッカソンだけではありませんでした。

懇親会中でLTやりたいと言ったところ、若手からベテランまで13名もの方が自分が発表したいと声をあげてくれました。 f:id:mf_sol_eai:20161205001041j:plain

せっかくなのでPepperくんに5分タイマーになってもらいました。 f:id:mf_sol_eai:20161205001140j:plain 5分経過すると罵声を浴びせながら中断させにかかります。

フリーテーマだったので、技術的な話から f:id:mf_sol_eai:20161205001248j:plain

サービスエリアの話まで f:id:mf_sol_eai:20161205001336j:plain

技術者としては、こういう場でドヤ顔しながら開発するのが一番楽しいですよね

LTリンク

LTまとめました

mf-sol-eai.hatenablog.com

LTってやっぱ面白い。そしてprezi難しい。

先日、当事業部内で懇親会を行ったのですが、ふとLT大会をやりたくなったので有志を数名集めてLT大会を実施しました。

若手の懇親会の場だったのでLTを知らない方も多く、ざっくりとLTとはなんなのか + オーディエンスも盛り上げてね的な意味を込めて(とはいえ Reveal.js と github.io を使ってみたかっただけという)頭出しスライド作ったのでうpしておきます。

たのしいLT祭り

懇親会でのLTということで、ノンテーマで実施したので技術的要素は限りなく薄め。 アニメの名言やらナンパ術やらをとくと語る中々濃い時間。 そして楽しみすぎてLT大会の写真は一切ないという・・・。

あと prezi も使ってみたかったので preziでやってみた。

IT昔話

preziはとても難しいという*1ことがわかったので成果は上々。パワポマンにはスタイリッシュなプレゼンは出来ないよパトラッシュ...

無論、内容を問われるLTもあると思いますが社内でやる場合など軽いLTの場も多くあると思うので、エンジニアの方々には是非とも自分を見せる場を活用していって欲しいですね。

*1:未完成品なのでいつか完成させたい...