おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

【小ネタ】PyUnoについての情報

LibreOfficePythonで扱うためのPyUnoというもの(Python-uno binding)があるのですが、これの情報どこかにない? と言われたのでリンク集。

p--q.blogspot.com

たぶんここから始まる資料一式が宝の山です。p--qさんのブログはすごく情報がいっぱいありますね(Asia Conference来てくれないかなー)。 ので、以下のリンクいらないかも。

Development/PyUno - The Document Foundation Wiki

TDF WikiのPyUnoのページ。悲しいぐらい情報がないですね ><

ので、以下はOpenOffice.org時代からの遺産。

PyUNO bridge - Apache OpenOffice Wiki

Python - Apache OpenOffice Wiki

Python-UNO bridge

日本語チームの安部さんのWindows環境でPyUno触る記事。

https://fixedpoint.jp/2018/03/23/libo-as-a-python-environment.html

LibOのUIテストはPyUnoで作られているんだけど、それについてのWiki。ログ機能によりUNO APIの呼び出しを調べる方法とか面白い。

https://wiki.documentfoundation.org/Development/UITests

LibreOfficeの中のPythonによるUIテストの実装はここらへんかな。

uitest - OpenGrok cross reference for /core/uitest/

忘れちゃいけないAPIリファレンス。ちょっとわかりにくいですね ><

LibreOffice 6.2 API Documentation

フローティングヘッダつきのWebサイトでスクロールしながらのスクショを撮る

私が仕事で愛用しておりますオープンソースなライブラリにAShotというのがありまして:

github.com

こいつはSeleniumスクリーンショットを超強力にしてくれるやつなのです。特定の要素だけのスクショ撮るとか、特定の要素を除外して撮るとか、関係ないところにぼかし処理を入れたりとか、さらに複数のイメージのdiffを取ってくれる機能まであって最高です。

なんといっても一番多用しているのが、「ブラウザ上で見切れている部分もスクロールしながらスクリーンショットを取ってくれる」機能*1なんです。むっちゃ便利ですよ。とくにエビデンスを重視するエンプラな現場では。

……が。こいつには一つ問題があって、「固定ヘッダがあるページだとヘッダが写り込んで、代わりにページの内容の一部が隠れてしまうのです。こんなふうに(サンプルはW3Schoolsの例を参考にさせていただきました)。

f:id:naruoga:20190209005245p:plain
ヘッダが写り込んでしまった悲しいサンプル

AShotには豊富なShooting Strategyがあるので、こういう機能もあるんじゃないの? と思って調べたんですが、どうもダメっぽく……こんなIssueが上がってました。

github.com

そっかーダメなのかーと思いつつみんなのコメントを読んでて……ん?

f:id:naruoga:20190209010008p:plain

So, you can change the attributes of an element with Selenium (using JavascriptExecutor).

My solution was change the visibility of header menu to hide it and make the screenshots.

After that, I turned back the attribute to the original one (just for keep the behavior along the tests).

With that change I can peform a full screenshot perfectly. Without black bars or overlapped menu.

(雑な訳)

Seleniumで(JavascriptExecutor)を使って要素の属性を変更できるじゃん。 ヘッダーメニューを非表示にしてからスクショを撮るってのがぼくの解決策だ。撮り終わったら属性を元に戻す(テストでの振る舞いを変えたくないからね)。 この変更でフルのスクリーンショットをカンペキに撮ることができたよ。黒いバーもメニューの重なりもなしでね。

おおーーー、なるほどー。

試してみた。こんな感じのメソッド用意して……

public static BufferedImage scrollshotWithFixedHeader(WebDriver driver, WebElement header) {
    if (!(driver instanceof JavascriptExecutor)) {
        throw new RuntimeException("the driver can not become JavascriptExecutor");
    }
    JavascriptExecutor jsexec = (JavascriptExecutor) driver;

    // ヘッダ部分だけスクショ撮る。JQueryなしのWebでも動くようにcoordsProviderを指定
    BufferedImage headerImage = new AShot()
            .coordsProvider(new WebDriverCoordsProvider())
            .takeScreenshot(driver, header)
            .getImage();

    // JSでヘッダを非表示に
    jsexec.executeScript("arguments[0].style.visibility='hidden'", header);
    // スクロールしながらスクリーンショットを撮る。ヘッダ部分は非表示になっただけなので空白になる
    BufferedImage bodyImage = new AShot()
            .shootingStrategy(ShootingStrategies.viewportPasting(100))
            .takeScreenshot(driver)
            .getImage();
    // ヘッダ表示を元に戻す
    jsexec.executeScript("arguments[0].style.visibility=''", header);
    // スクロールして撮った画像にヘッダを貼り付ける
    Graphics2D graphics = bodyImage.createGraphics();
    graphics.drawImage(headerImage, 0, 0, null);
    graphics.dispose();

    // 加工後の画像を返す
    return bodyImage;
}

呼ぶ側はこんな感じ*2。ここで save()BufferedImage を引数で渡されたファイル名で保存するメソッドです。

open(new File("HTML/header.html").toURI().toURL());

BufferedImage screenshot = scrollshotWithFixedHeader(
        getWebDriver(),
        $("#myHeader").toWebElement());
save(screenshot, "test2");

f:id:naruoga:20190209005935p:plain
ちゃんとスクショ撮れた!

メソッド名もいいかげんだし、JSのコードとか結構雑だし*3、テストもちゃんとやってないので、もちょっとブラッシュアップする必要がありそうですけど、まあ一応動いたので満足しました。という、お話でした。

PS. 関係ないけどはてなブログの脚注 ((...)) って、中で ` 使えないんですねー。知らなかった。

*1:が、こいつIEだと動かないという弱点があります。内部で呼んでるJavaScriptIEだとダメという話なので、直したPull-reqを投げてるんですけど、マージされる気配がない……というか、開発が停滞している気配がある。フォークしちゃおうかなあって考えてます。

*2:Selenium WebDriverのラッパーのSelenideを使ってるので open() とか $() とか getWebDriver() についてはSelenideについての解説を参照してくだされ。

*3:element.style.visibilityの値いきなり上書きしちゃうのは大丈夫なのかな……。

LibreOfficeな公式ブログたち

Advent Calendar 12/19が空いてたので小ネタ。

LibreOfficeを支える非営利団体であるThe Document Foundationには複数の公式ブログがあります。

The Document Foundation Blog -

ここがメイン。私もちょろちょろ引用してるので、私のブログをご覧の方はたいていご存知なんじゃないかなと思います。リリース通知やさまざまなお知らせ、コミュニティメンバーへのインタビューなど面白い記事がたくさんなので、よかったら定期的に覗いてみてください。

それ以外に(今のところは)二つの分野別ブログがあります。

design.blog.documentfoundation.org

デザインチームのブログ。LibreOfficeの新しいUIについての記事や、今後のUIについてのアンケート依頼などの記事が載っています。そんなに更新頻度は高くないですが興味深いですね。

qa.blog.documentfoundation.org

QAチームのブロク。月刊の「QA Report」が主……というか、これを定期的に読むだけでも価値アリです。

ということで手短ですが。

LibreOfficeへ寄付する(その2;Flattrを使ってみる)

2018.12.13 追記:昨日の記事にも追記したんですが、なぜかPayPal使えるようになっちゃいました。でもPayPalを用いたTDFへの継続的な寄付(recurring donation)とFlattrは位置づけが違うので、この記事も無駄にはならないかなーということでお願いします。


前回のつづき。

naruoga.hatenablog.com

はてさて、PayPalがダメだとしても、「少額でもいいから継続的な寄付がしたいなあ」という方に使えそうな選択肢が、Flattrです。

flattr.com

寄付ページには、英語版にも:

f:id:naruoga:20181208022530p:plain
私たちにFlattrできるよ

日本語版にも、

f:id:naruoga:20181208023115p:plain
ちょっと地味ですけど

記載があります。

が、そこから張ってあるリンクに跳ぶと、

f:id:naruoga:20181208023453p:plain
さっぱりしたページ

……で、ここでどうしろと?

さっぱりわからんのでしばし悩みましたが、無精しないでFlattrのサイトをちゃんと読めば書いてありました。でもまあ英語なので、簡単に説明しておきます。

そもそもFlattrとはなんぞや? 「開発者(Creators)」と「貢献者(Contributors)」をつないでカジュアルに寄付をするサービスです。調べたら2010年ぐらいに日本語の記事が出てた。全然知りませんでした。情弱です。

www.infoq.com

まあそれはともかく、Flattrのサイトの説明も、Creators向けとContributors向けに別れてるので、上のContributorsをぽちっと押して貢献者(この文脈では寄付をしたい人)向けの情報を表示しましょう。

flattr.com

サービスの概略はこの絵にあるとおりで:

f:id:naruoga:20181208024634p:plain
概念説明。わかりやすい。これ読めばこの(私の)記事いらんのでは

  • ユーザー登録して
  • Subscriptionという「月々支払う金額」を決めて
  • ChromeFirefox(他のブラウザにあるのかどうかは調べてない)のアドオンを入れて
  • 「このサイト・サービス・なにかに寄付したい!」と思ったら、Flattrなリンクでアドオンを操作してFlattrする

ってな感じですね。

ユーザー登録はメールアドレスとパスワード設定するだけ。超かんたん。確認メールが飛ぶのでリンククリックで完了。

Subscriptionは、スクショとか残してないんですけど、「総額これぐらいなら払ってもいいなー」という金額を設定し(私はビンボ臭く月 $10 にしました)、カード情報を入れる。ぐぐって出てきた記事だとPayPalとか使えるっぽく書いてたんですが、うっすらとした記憶としてはカードだけだったように思います。

サインインしてFlattrのダッシュボード飛ぶと、「アドオン入れる?」って出るので、それに従って導入すればOK。

f:id:naruoga:20181208030142p:plain
こんな感じでアドオン導入が促される

入れるとこんなアイコンが追加されるはず。

f:id:naruoga:20181208030736p:plain
何やら怒ってます

赤くて!もついてるので、アイコンクリックすると、

f:id:naruoga:20181208031003p:plain
サインインを促される

サインインしてねと言われるので仰せのままにクリックすると、

f:id:naruoga:20181208031202p:plain
ちゃんと読んで同意しましょう

以下の情報にアクセスするけどいい? と聞いてきます(雑な訳ですし変わるかもしれないのでちゃんと読みましょうね)。

  • 公的IDとユーザー名
  • 寄付したいFlattrコンテンツ
  • Flattrした履歴

同意できるならAuthorizeをぽちっとします。これで準備完了。アイコンが地味に変化します。

f:id:naruoga:20181208030342p:plain
地味なアイコン

これで準備完了。たとえばLibreOfficeの日本語ページ

ja.libreoffice.org

にアクセスして、アイコンをクリックすると、

f:id:naruoga:20181208032257p:plain
何やら英語でいろいろと

こんなダイアログが出ます。「デフォルトではこのサイトではFlattrはオンになってないので、このサイトにFlattrすることはできないよ。有効にしたいなら右のスイッチをONにしてね」みたいな感じですね。ので、ONにすると、

f:id:naruoga:20181208032711p:plain
これでFlattr可能に

「Flattr Now」というボタンが押せるようになるので、ぽちっと押せばFlattr完了。

ダッシュボードで状況も確認できます。

f:id:naruoga:20181208033724p:plain
こんな感じ。グラフに変な線が出ちゃってるのは環境の不具合です

実はLibOに寄付できるだけで満足してて他のサイトとかの対応状況についてはまだ把握してなくて、それはこれからなんですが、まあ、LibOに寄付するという目的は達したので。はい。

LibreOfficeへ寄付する(その1;PayPal使えないのでクレカ払いにする)

2018.12.13 追記

先日の福岡LibreOffice勉強会で、ほらこうやってエラーになるんですよ……と、みんなの前でデモったら、なぜか? PayPalで支払い通っちゃいました。おっかしーな、この記事を書いたときにはダメだったし、なにも設定変えてないんですが……もしかしてPayPalの中の人に読まれてる?(ないない

ということで、以下のネタおよび翌日のネタは、PayPalで支払いやってみたけどダメだった人向けです。


小ネタです。

LibreOfficeに寄付してますか?

いや、厳密にはLibreOfficeに直接寄付するというより、LibreOfficeの母体となっている法人The Document Foundation(ドキュメント財団、以下TDF)に対する寄付なんですけどね。

ともかく、TDFは各種インフラを維持管理したり、そのインフラ管理者を始めとした各種のフルタイムワーカーを雇用したり、メンバーが活動する資金……たとえばLibreOffice Conferenceに参加したり、地域コミュニティがイベントを主催し運営したり、配布物を作成したり、……といったことを支援したりしていますので、皆様の寄付はそういった活動に使われるわけです。ぜひぜひ、寄付のほうご検討くださいませ。よろしくお願いいたします。

さて、TDFの英語の寄付ページはこちらなのですが:

www.libreoffice.org

があるので注意)、このページを見ると:

f:id:naruoga:20181205212546p:plain
LibOの寄付ページ

いかにもPayPalで払ってほしそうですよね……が、残念ながら日本からPayPal送金しようとすると、

f:id:naruoga:20181205212755p:plain
日本のPayPalアカウントでは寄付ができない!

怒られちゃうのです。

ちなみに上のスクショにもあるように、TDFは「少額でもいいから継続的な寄付」をなるべくならお願いするようになっていて、寄付ページは「毎月4ドルずつ払う」がデフォルトになっております。が、「Or click here to make a one-time donation instead」のボタンをポチッと押すと、

f:id:naruoga:20181205213136p:plain
一回限りの支払い。こっちならカード払い可能

こういうふうになって、一回限りのお支払の画面になります。こっちなら、TDFの契約している決済サービスにクレジットカード情報を登録すれば、カード決済可能です。

結局、少額の場合カードの決済手数料が馬鹿にならないので、継続的な寄付についてはPayPalだけということになってるということのようですね。

他にもビットコインでのお支払とかも可能らしいので、お持ちの方試してみてはいかがでしょう。

日本で継続的な寄付をする方法としてオススメできそうなものについては、「その2」で紹介します。

……なお、日本の寄付ページでは:

ja.libreoffice.org

ちょっとクラシックな作りですがこいつだと「継続的な寄付」の選択肢がないので、迷いがないといえばそうですね……。このページも直したほうがいいかなあとは、ぼんやり考えてます。

LibreOffice Conference 2018 Tirana 裏レポート

どうもこんにちは。今年もあっという間に12月になってしまいました。クリスマスまで、また新しい年まで、あとちょっとですね。

ということでこのエントリーは、LibreOffice Advent Calendar 2018の初日ということになります。ちょっと今年は(例年以上に)エントリーが少なくて寂しいですね。皆さん今からでもぜひご参加を。

表題のとおり、LibreOffice Conference 2018 Tiranaに行ってきました。カンファレンスレポートは日経xTECHさんに載せていただきました:

tech.nikkeibp.co.jp

が、ここではレポートに書かなかった細々としたあれこれを。

2015年にも同じネタを書いたのですが、LibreOffice Conference(以下LibOCon、通称りぼこん)に限らず、海外のカンファレンス参加してみようかなーという人の参考になればいいなと思いまして*1

お金とかそういう話

私にとってオープンソースの活動は完全に趣味でございまして(仕事に関係してることもなくはないけど)、お財布事情はやっぱりちょっと気になるところであります。

ありがたいことにLibreOfficeをホストするThe Document Foundation:

Home | The Document Foundation - The House of LibreOffice and Document Liberation Project

は、そのメンバーがカンファレンスに参加する場合その渡航費を援助してくれます。メンバー以外であっても、メンバー(例えば私とか)が推挙してかつトークが採択された場合もたぶん援助対象になると思います。大雑把に、開催都市への往復交通費(飛行機だけじゃなくて、たぶん請求すれば都市間の鉄道も)と滞在費は出ると思って大丈夫です。TDFを支えるAdvisory Boardと寄付をしてくれている皆様に感謝感謝。

とはいえ、一度立て替え払いして後日精算なので、旅費がかからないほうが都合がよいことはそうなのですが。

でまあ、旅費については大雑把にこんな感じ。

費目 費用(日本円) 備考
航空券 168,910円 ターキッシュエアラインズ
成田 - Istanbul - Tirana
滞在費 12,416円 AirBnB 9月24日〜9月30日
合計 181,326円

航空券については、Tiranaはそんなに日本ではメジャーな都市じゃないので、やっぱりちょっと高いですね。

一方、宿泊は安いですね。6泊だから一泊あたり2000円。これはエアビーだからというわけじゃなくて、普通のホテルでもそんなに高くはないみたい。

LibOCon自体は参加費無料です。なおかつ、ランチと公式パーティの食事(ドリンク1杯つき)、HackNight(集まって話したり作業したりするイベント)の食事つき。なので、現地ではそんなにお金はつかいません。スポンサーさまさまです。

Tiranaは物価は安くて、現地通貨Lekはほぼレートが1円 ~= 1Lekなので数字に弱い私でも安心。ご飯が半額、お酒が2/3ぐらいかなーざっくり。15000Lekぐらい換えて中途半端に3000Lekぐらい余ってます……(なんか再両替するのも微妙な金額なので今でも財布に入ってる)。 現地はほぼニコニコ現金払いだったので、おみやげや空港から中心部までのバス代、観光で博物館入ったときのチケットなども含め12000円ぐらいしか使ってないということか。安上がりだ。

Lekへの両替はカードでキャッシングするのが簡単です。ATMは空港にもあるし、市街地でも銀行にはだいたい24時間のATMがありました。

ただ、噂によるとカード会社によってはアルバニアからのキャッシングを止めてることがあるみたいで(電話すれば解除してもらえるらしいですけど)。私は大丈夫でした。

空港や街に両替屋はあるんですがたぶん日本円からの両替は難しいのではないかな……? ユーロ持っていくと安心かも。

交通手段など

前述の通りTiranaはあんまり我が国ではメジャーではないらしく、日本からの選択肢はあんまりなくて、乗り継ぎ1回だとターキッシュ、アリタリア、ブリティッシュあたりで*2、お値段的にターキッシュにしました。週末を外したり乗り継ぎ回数増やしたり、あといちどトルコで出国したりするともっと安かったりするらしいのですけど、わたくしのばあい可処分有給休暇がですね……。

ターキッシュだと当然乗り継ぎはIstanbulで、空港のWi-Fiがたしか無料枠1週間で2時間までだったかな? あとサインアップのページの使い勝手が最悪で、めっちゃイライラしましたが、繋がってしまえばまあ安楽。

HISの銀座店で最初に見積もったときは14万ぐらいだったんですが、私のよくないくせ(旅行のチケットとか、なんか日程をばちっと決めてしまうものがなかなか確定できない)でとっとと手配しないうちに値段が上がってしまい、慌ててネットで調べて押さえたら、帰国日を間違えていた*3 あと、ANAのWebページでマイル後付しようと思ったらなぜか「搭乗者情報不一致」で跳ねられてしまったのはなぜだろう。まあ真剣にマイルためてるわけじゃないんで、別にいいんですが。

で、Tiranaの空港から市街まではバスが出てます。たしか200Lekとかで激安。1時間ぐらいかな。

Tirana市街はそんなに大きくもないし、そもそも鉄道はぜんぜん発達してないお国柄なので交通機関は全部徒歩でした。ドライバーも歩行者もちょっと強引な感じでクラクションブーブーなってるし、歩行者は信号赤でも横断歩道じゃないけっこう交通量があるところでも平気で渡ってるし、ちょっとおっかなかったですけど普通に信号守って歩道歩いてる分には大丈夫。あんまり財政的には豊かではないらしく歩道はタイルが剥げてたり穴が空いてたりしてましたので、よそ見しながら歩くのはよくないですね。

宿泊

前述のとおり、宿は今回もAirBnB(エアビー)でした。

エアビー病気したりしたときはリスクもあるし(たぶんサービスとして保証はあんまりなくて、ホストのご行為に頼るところは多々あると思う;チェコのときはホストが親切にしてくれた)、どうせ旅費出るので普通のホテル泊まってもいいと思うのですが、私わりとエアビーが好きでして。ホストとお話したりするのが楽しいんですよ。海外だといい具合に気が張ってるせいか朝はちゃんと起きられるし夜もしゃっきりしてるんで、LibOConのときはいつもエアビーです。

ただ、あんまり会場との位置関係を気にせず取ってしまったので、会場からも、夜ゴハンを食べに行ったりする繁華街からも微妙に遠くて、毎朝40分かけて歩いて会場入りし、やっぱり40分ぐらいかけてご飯食べに行き、帰りも20分ぐらい歩いてました。まあ、たまには歩くぐらいが健康にはよろしい。

日程とか

9月の後半の連休にかぶってたので4日休めばOKだったんですが(弊社は夏休みが7〜9月中に3日自由にもらえるので、+1日有給取ればよい)、航空券の手配間違えて10/1も休みになってしまったのは前述のとおり。まあでも、カンファレンスのあとほぼまる2日自由な時間があって観光できたのは結果的にはよかったですね。カンファレンスの前は発表の準備とかあって気持ちが落ち着かないので……。

日本発が9/23(日)で現地到着が9/24(月)朝、11時ぐらいに宿について(ホストに着いたよ!って言ったら、じゃあおいでよ、コーヒーでもどうぞというので甘えさせてもらった)、近くでランチ食べてから発表資料作成して、夜はもう入ってるメンバーと合流してご飯食べてと。

9/25(火)は「誰かランチ行く人いる?」「じゃ、行く行く!」って4人ぐらいで集まって、アルバニアの伝統料理を出してくれるレストラン:

Oda Restaurant

に行って(私は手前に写ってるTavë dheuっていうの食べました。羊レバーとカッテージチーズ。これは割と気に入りました):

f:id:naruoga:20181201183801p:plain

コミュニティデーで、参加登録すませて名札とカンファレンスバッグとTシャツもらって、

f:id:naruoga:20181201183831p:plain

コミュニティについてのいろんなことを議論しました。この議論の内容については、前述のxTECHさんのレポートに書かなかったものもあるので、また別のエントリーで紹介しようと思います。この日の夜はウェルカムパーティで、色んな人と話せてよかったんだけど食べ物がぜんぜんないお店だったので途中で抜けて台湾勢と合流して晩御飯食べたりしました。ラムチョップが美味しかった。

カンファレンス本会は9/26(水)〜9/28(金)で、私の発表は27日。26日の夜がHackNightで27日の夜がカンファレンスディナー、28日は公式のイベントはなかったんだけど、それはみんな、飲みにいくよねってことで飲んだり食べたりして。毎日朝7時前に起きてシャワー浴びて朝ご飯食べて歩いて会場入りして英語の発表一日聞いて休み時間も英語でしゃべって夜の会場へも徒歩で移動して、日付が変わる頃に帰ってきて寝るという健康的なんだかなんだかよくわからない日々でした。

Tiranaという街とか観光とか

そういやTiranaという街について説明してませんでした。アドリア海沿いに位置する小国、アルバニアの首都です。

日本語でぐぐると「ヨーロッパ最後の秘境」とか書いてあるし、隣国はコソボなので紛争のときに小火器が数百万丁ほど行方不明になったよ(それを使った犯罪があったという報告はないけど)みたいなことを読まされて、ちょっぴりドキドキしたけど、ぜんぜん、いい街でしたよ。コンパクトで、街並みは綺麗で、気候はよくて。会期中はずっと晴天だったんですが、聞くと概ね気候はよいみたいです。地中海性気候ってやつすね。

オスマントルコ帝国の支配下にあった時代が長くて、イスラム教徒が一番多いんだったかな? ただ、イスラム教国っぽいあんまり厳格な感じはしなくて、街の中心の広場にも一番近いところにはモスクがありますが、ちょっと離れると教会もあるし、普通にビールも飲めるし :)。

9/29(土)の午前中はカンファレンススタッフがTiranaツアーを企画してくれたので参加しました。

f:id:naruoga:20181201183427p:plain

これは雲をイメージした、日本人のSou Fujimotoさんという方がデザインしたオブジェなんだそうです。エアビーのホストさんいわく「でもおかしいよね、この国はいつもいい天気で、雲はあんまりないんだけど」だそうで。

その午後は国立歴史博物館に。

f:id:naruoga:20181201183526p:plain

日本のような島国とはやっぱりちょっと違う複雑な歴史が感じられる見どころのある博物館でした。でも、一部やる気がつきたのか、解説文がアルバニア語しかなくて読めなかったのが残念。

翌日はエアビーのホストさんが観光案内するよ?って言ってくれたのでまた色々連れて行ってもらいました。写真は共産党政権下の核シェルターを改装して作った「BUNK'ART 2」という軍事・警察関係の博物館。これがもうねえ、洗脳キャンプとか秘密警察とか国境警備隊とかの胸が悪くなるような展示で、実に素晴らしかったです。オススメ(真顔)。人間はここまで非人間的になれるんだなあという。

f:id:naruoga:20181201183624p:plain f:id:naruoga:20181201183657p:plain

まーそんなわけでTiranaいいところです。普通に観光してもいいところだと思う。私はいけなかったけど、アルバニアの他の都市もいいみたい。私もまた行きたいです。

ダラダラと長文になってしまいました。来年はスペインのAlmeriaだそうで、ここもとても美しい都市のようで今から楽しみ。みなさんもぜひ、LibOConに行きましょう。こういっちゃなんですがコミュニティのサイズは小さいしアジアからの声をみんな求めてるんで、トークが採択されるのは(=旅費補助を受けられるのは)そんなにハードルは高くないです。

では読んでくれてありがとうございました。Faleminderit(ふぁれみんでーり)!

明日は榎さんの「LibreOfficeを使う上で知っておくと便利なこと一覧」だそうです。楽しみですね。

*1:この文章どこかで読んだことあるなと思った方、はい、2015年のレポートからのコピペちょっと編集版です。って、リンク張っておいて読んだことあるもなにもないか。行くたび同じネタ書いてるんですけど、2016年は入院したし、昨年2017年は休みが合わなくて行けなかったので。

*2:……今調べたらルフトハンザとかKLMとかもあるな。まあ、どっちにしろ高いですけど。

*3:9月30日(日)着にするつもりだったのが、月曜着になってた;まあ結果的には、9月30日って台風来た日なのでたぶん飛行機飛ばなかっただろうし、結果としては変わらなかったと思うのですけど。

docker-android + AppImage版Appium DesktopでAndroidテスト自動化の環境をさっくり作る

うっすいネタ、いわゆる「使ってみました」ネタで恐縮です。あと、タグSeleniumってつけてますが兄弟?プロジェクトのAppiumネタです。

私の本業はいちおうソフトウェア自動テストアーキテクト*1 なわけです。主にSeleniumを使ったWebの自動テストが得意領域ってことになってるんですが、その周辺領域であるAppiumを用いたモバイルの自動テストはあんまり手を動かした経験がなく、教科書レベルのことは言えるけど……ってのがコンプレックスでした。

最近いろいろあって残業することなく早く帰るようにしてるので、自由になる時間をYouTubeの動画*2 観て溶かしてないで、ちったー手を動かしてみますかーってことで、マイパソコンでAppiumのテスト自動化開発環境を作ろうと思い立ちました。仕事ではJava + Selenide*3 なんですけど、まあ個人の遊びなので違う言語ってことでRubyで。

ご存知の通り?私は個人ではUbuntuしか使ってないので、Ubuntu上で環境を作りたい。なのですが、AppiumってNodeアプリなので、Nodeを入れなきゃなのですが、NodeもまたこれがLinuxディストリビューションのパッケージングポリシーと合わないことおびただしい*4 のでコンテナに閉じ込めたりしたい。さらにいうとAndroid SDKとかの管理もめんどくさい。なんかいいのないかなーとググっていたら。素晴らしいものがありましたよ。

GitHub - butomo1989/docker-android: Android in docker solution with noVNC supported and video recording

AndroidのAVDとAppiumを封じ込めたコンテナ。docker run一発で全部入り環境が立ち上がる。AVDの操作ははVNCとか入れずにブラウザーで確認可能。動画記録機能まである。これは最高なのでは……。

ということで使ってみました。

Ubuntuのバージョンは18.04 LTS(bionic beaver)です。

docker-android使ってみよう

むっちゃ簡単です。

docker run --privileged -d -p 6080:6080 -p 5554:5554 -p 5555:5555 -p 4723:4723 -e DEVICE="Samsung Galaxy S6" -e APPIUM=true --name android-container butomo1989/docker-android-x86-8.1

-e APPIUM=true でAppiumサーバーも一緒にあげてます。

ちょっとコンテナサイズでかくて、初回実行時にはpullにしばらく待たされました*5 けど、あっさり動いた。ちょっと感動。

f:id:naruoga:20180713222744p:plain

AppImage版Appium Desktopからつなぐ

Appiumサーバーちゃんと動いてること確認したいですね。

そのためには(もちろん、今後使うからでもありますけど)Appiumの開発ツールであるAppium Desktopも使いたい。しかしこいつも依存関係汚すのはやだなー。そう思いつつ公式の配布先↓ 見に行ったら。

github.com

あるじゃん。AppImage版。

AppImageについては深入りしませんが*6、よーはファイル取ってきて実行権限つけるだけで、インストール不要で使えるパッケージ。これなら環境汚さないしもう使わないと思ったらファイル消すだけでOKです。

早速取ってきて(依存関係全部抱いてる関係でちょっとでっかいです)、実行権限つけて起動。

f:id:naruoga:20180713223522p:plain

今回はdocker-android内でAppiumサーバー動いてるので「Start Server」は押さずに、メニューから「File」>「New Session Window」を起動。セッション画面を起動します。

で、Desired Capabilitesを以下のようにして*7、単に設定画面を開いてみます。

{
  "platformName": "android",
  "deviceName": "device",
  "appActivity": "Settings",
  "appPackage": "com.android.settings",
  "takesScreenshot": false
}

Start Session! うりゃ!

f:id:naruoga:20180713224510p:plain

ちゃんと動いてる! やったね。

スクリプトから起動してみる

ではRubyスクリプトから起動してみましょうか。せっかくなので今度はアプリケーションをサイドロードして起動して、それを操作してみたいですね。

っと、その前に、apkを導入するときには、apkのあるフォルダを /root/tmp にマウントしろとドキュメントに書いてあるので、動いてるコンテナを止めて再起動します。スクリプトを作るフォルダにapkは置くことにして、雑に $PWD をマウントします。

docker stop android-container
docker rm android-container
docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -e DEVICE="Samsung Galaxy S6" -e APPIUM=true -e CONNECT_TO_GRID=true -e APPIUM_HOST="127.0.0.1" -e APPIUM_PORT=4723 -e SELENIUM_HOST="172.17.0.1" -e SELENIUM_PORT=4444 -e MOBILE_WEB_TEST=true -v $PWD:/root/tmp  --name android-container butomo1989/docker-android-x86-8.1

あれ、コマンド履歴見直すと CONNECT_TO_GRID*8 はいらんのでは……。まあいいや。

アプリは、わたくし普段からAndroidアプリ開発してるわけではないので*9 手持ちのapkはなく、ので、Appiumのサンプル からApiDemos-debug.apkを取ってきて手元のディレクトリに置きました。

で、次のようなRubyスクリプトを書きます。

require 'test/unit'
require 'appium_lib'

class SimpleTest < Test::Unit::TestCase
    def setup                 
        desired_caps = {
            caps: {
                platformName: 'android',
                deviceName: 'device',
                app: '/root/tmp/ApiDemos-debug.apk',
                appActivity: '.ApiDemos',
                appPackage: 'io.appium.android.apis', 
                takesScreenshot: false,
            },
            appium_lib: {
                server_url: 'http://localhost:4723/wd/hub'
            }
        }

        driver = Appium::Driver.new(desired_caps, true)
        Appium.promote_appium_methods self.class
        driver.start_driver.manage.timeouts.implicit_wait = 20
    end
    
    def teardown
        driver_quit
    end

    def test_sample
        puts "hello"
    end
end

これでさくっと動いてしまいました。いやーすばらしい。

f:id:naruoga:20180713232604p:plain

今のところテスト本体は空っぽなので、単にアプリ起動できたところまでしか確認できてませんけど。

これから、テストちょろちょろ書いていこうと思います。今回は 'test/unit' 使ってるけど、このテストフレームワークがいいよ! という推薦があれば教えていただきたいです。かなり昔に教えてもらったTurnipが気になってますが……。

まあともかく、docker-androidおすすめです。あとLinux使うならAppImage版Appium Desktopもチョー推薦です*10

以下おまけあり。読みたい方は「続きを読む」をクリックしてください。

*1:自動テストがprofessionであって、自動がつかないテストについては不勉強の至りです……。

*2:高田馬場ゲーセンミカドの動画がお気に入りです。

*3:Selenideいいですよねえ。機能も実装も素敵。もしJavaで素のWebDriver使って苦労してるならぜひ試してみましょう。

*4:言語系パッケージシステムのライフタイムと、Linuxディストリビューションのそれとは大きく違うのでそれはしょうがないですよね。

*5:というか、待ちきれなくて寝てしまいました。うちはあんまりネットワーク太くないので……。

*6:公式サイト参照。

*7:AppiumのRubyサンプルコード から拝借。

*8:こいつの意味は続きがあればそこで書くかも。さしあたりは公式読んでください。

*9:この活動の一環として将来は作ってみたいなとは思ってますけど……いつになるかは不明。

*10:というか一般にAppImageは便利。LibreOfficeとかでも。

続きを読む