Read “Functional Programming: A PragPub Anthology”

Functional Programming: A PragPub Anthology を読んだ。まだβだったけれど、内容はだいぶまとまっててあとは微調整して発売という感じを受けた。

The Functional Paradigmから入り、Scala、Clojure、Elixir、Haskell、Swiftと関数型というテーマに絡めたそれぞれの言語の特性に触れながら話は進む。それらがひととおおり終わり、考え方を経験した後、Going Deeperということでそれらを再び題材に、より言語毎の特性、テスト(コード)の話、タイプシステム、The DCI architecture、そしてLuaと理解を深めていく。

この書籍をまるっと読むと、いくつかの言語から関数型言語、関数型な考え方に触れ、それらを学ぶことができる。さらには軽くそれらに触れることで、いわゆる写経もやりながら理解を深めることができるので、とっかかりとしても有用な内容だった。特に前半は、その言語に触れたことがある人からすると読み物的な内容に見えるので、考え方を整理するという形で触れることができると思う。

個人的にはElixirやSwift、Testing周りが関係が強いので、そこら辺は特に楽しむことができた。

例えば、ElixirやSwiftのProtocolの話。SwiftではProtocolはGlobalスコープに対して定義される一方で、Elixirでは特定の型に対して定義することができる。そのため、影響範囲を限定することができるのでより安全に利用することができるという話も。

テストの話としては、Elixir、Haskellが題材になっていてよかった。Elixirの話では、TrueStoryを題材にして、可読性の高い(テストしたいシナリオ・ストーリーを理解しやすい)テストコードの書き方に対しても言及している。その中で、パイプ演算子を使った関数型としての書き方に触れながら話を進めている。

Haskellでは、型システムのほか、C言語で書かれたコードをHaskellでラップしてテストコードを書いていく方法を載せている。ほかの言語をテストするためにHaskellを使う形は興味深かった。

やー。思いの外、Elixirに関する話が多かったのとHaskellを使った説明も多く、個人的にはそれだけで満足度が高かった。Haskellはがっつり触れたことはなく、考え方を学ぶために触れている側面が強いけれど、触れる機会が増えてきたらまたこの書籍でさっとHaskellは頭の中を整理したい気分。

[Swift]try!Swiftで学んだことまとめ

私は職場で作ってきたテストの話のうち、UI Testに近いところの話をしました。

英語での発表は初めてだったのですが、一部想定通りに話せなかったところがありながらも無事に終えることができ、ホットしました。日本以外から来た人含め、いろんな人から英語も聞き取りやすかったし内容も良かったと言って貰えて、ひとまず安心しました。

お題の悩み

私はSwiftを使ったテストの話(Unit Test)をするかとか、protocolベースのDIの話をテストに絡めるか、UI Testの話をするか悩んでいました。

推薦されたことで話すことができるようになったので、try!Swift全体の中でそれぞれの話す内容が重ならない程度の話題にした方がバリエーション豊かになって良いかなと思い、UI Testsやその周辺の話をしました。

ただ、このレイヤの話はSwift自体でそこの話をするにはネタがない。XCUITestとかだとSwiftではなくiOSフレームワークの話になりますしね。半端にSwift x XCUITest(内部コードとか)の話をするよりは、テスト全体とUI Tests、Re-Engineeringnの話をする方が独自性を持った話ができるかと思い、結果的には話すことにしました。

結果的には、unit test関係で想定していたセッションの内容は他のスピーカーの方々が行なっていたので、重ならずに良かったかもしれません。

運営の方からは良かったとフィードバックをいただけたので、推薦いただいたことに対しては役目を果たせたと感じてはいます。

他のセッション

すでに nowsprinting さんがまとめを書いていたので、テストに関してはそこにお任せ。
http://nowsprinting.hatenablog.com/entry/2017/03/05/061441

内容自体はprotocolやstruct付近を使った話で、functional programmingもかじっていると理解を深めることができる内容でした。

The Two Sides of Writing Testable Code

ここで出てきた “co-effect” に関しては以下が参考になるらしいので、少し読んでみようと思います。

ReactNative

3日目のハッカソンでは、その間に行われたReactNativeのゲリラワークショップを経験しました。

ReactNativeのテストには、JSレベルでは jest、UIレベルだと testID を付与してからのUI Test系ですね。
JSの世界でテストが実行できると、unit testでもXCTestよりも素早くテストのサイクルを回すことができて良いですね。

最後に

本当にお疲れ様でした & ありがとうございました

「Swift実践入門」を読んだ

同僚や、知人が書かれていることもあり、Swift実践入門を読んでSwift言語への理解を深めてみました。

私個人のスキルでいうと、公式のThe Swift Programming Languageの2.1向けのものや、Functional Swiftとかの英語書籍を読んだり写経したりして簡単なSwiftプログラムを書いたり読んだりはできる感じです。iOSエンジニアとして会社でコードを書き続けているわけではないです。

内容は、うろ覚えだったり把握していなかったとところを補足することができ、言語自体の学びを整理することにとても役立つ書籍でした。iOS周辺の開発になると、こことは別にAPIへの理解も必要なのですが、私はそこはまだまだ足りていない…

全体的に、Swiftの様々な機能をどういう形で使うと良いのか、というところで参考になりました。以下、私が読んでいてメモしておきたかったところをメモしておきます。

2章

Swiftにおける範囲型、Optionalの話とか、復習になった。特に、 ?! のforce unwrapの話。実行時に評価されて無理やり値を取り出す ! と、 .none になる ? の話とか。

テストコードだと、例えばEarlGreyのようなやつだと実行時評価が必要なことが多く、 ! を使ったりしていた。けれど、Swiftの理想でいうとやっぱり ! は思想に反する(実行時にしか評価されないし、クラッシュするし)のでやぱりよくないのだなーと。

as? によるダウンキャストや as! as? によるアップキャストの話もちらほら。

3章

switch の制御で以下のようにかける形、Erlang/Elixirを学んでいたので自然な感じだった。こういうの書き始めると、Androidの世界にも時折欲しいと思う時がある…

switch a / 2 {
case let b where b < 2:
    print("lower than 2")
case let b where b >= 2:
    print("more than or equal to 2")
default:
    print("no")
}

繰り返しの for ... in ... {} は使ったこともあるのですが、 case 使う場合もinを支えたのですね。把握していなかった…

for value in 1...4 { print("\(value)") }
for case let (2, value) in [(1, "a"), (2, "b"), (3, "c")] { print("\(value)") }

switchの中、 break を置くことはよくやることですね。Javaとかやっていると。これ、breakしないと多くの場合は次々と case を実行していくのですが、swiftでは明示的に fallthrough を与えないといけないのですね。

let a = 10

switch a / 2 {
case let b:
    print("first")             // "first\n"
    fallthrough
case 5:
    print("after fallthrough") // "after fallthrough\n"
    break
    print("after break")
default:
    print("no")
}

あと、 breakやcontinueの遷移先を制御するために label をつけることができるとは知らなかった…

4章

@discardableResultがあったのですね。 _ = someMethods で処理を書いていた。どのみち、使わない、使わなくて良いことを明示するスタイル。

Swift、以下のような形で副作用をもたせた書き方もできたのですね。JavaとかRubyといったオブジェクト指向の書き方では書いていたのですが、Swift(のstructとか)Elixirとかみたいな関数型をメインで触っていると、こういうことが頭から離れることが多い…

func add(_ x: Int, _ y: Int, _ a: inout Int) {
    a += x + y
}

var a: Int = 10
add(10, 10, &a)
a // 30

7章

protocolの話。
Swiftはprotocol oriented programmingと言われるように、このprotocolが重要になります。
associatedTypeによる、protocolでは抽象的な文字を定義しつつ、具体的な型はそれを受け継いだstructなどで定義する。それらの定義は明示しなくとも類推されて補完されもします。個人的には、Swiftは明記によって安全性を表現しているので、推論ばかりに頼りたくない(明示していきたい)なーとも思います。

protocol SomeProtocol {
    associatedtype AssociatedType

    var value: AssociatedType { get }
    func someMethod(value: AssociatedType) -> AssociatedType
}

struct SomeStruct : SomeProtocol {
    typealias AssociatedType = Int

    var value: AssociatedType
    func someMethod(value: AssociatedType) -> AssociatedType {
        return 1
    }
}

struct SomeStruct2 : SomeProtocol {
    var value: Int
    func someMethod(value: Int) -> Int {
        return 1
    }
}

struct SomeStruct3 : SomeProtocol {
    struct AssociatedType {}

    var value: AssociatedType
    func someMethod(value: AssociatedType) -> AssociatedType {
        return AssociatedType()
    }
}

指定する型とそれを受け継いだサブクラスの話。
それら。

where 句によるprotocolに対するextensionの制御の話。例えば、以下だとWebContentの型を持ったやつ。

protocol Item {
    var name: String { get }
}

protocol WebContent {
    var url: String { get }
}

extension Item where Self : WebContent {
    var description: String {
        return "hi"
    }
}

struct EBook: Item, WebContent {
    let name: String
    let url: String
}

struct Book: Item {
    let name: String
}

いくつかの標準ライブラリに付与されるプロトロル。

8章

Any関数はダウンキャストが必要。

if let int = something as? Int {
  // something
} else {
  // else
}

なので、ジェネリクス良いですね。

10章

参照型のクラスと、値型の構造体。その選定基準がとても為になった。

クラスは参照型なので、新しくインスタンスを作ってもそのインスタンスに保持されている値はつながっている。つまるところ、副作用がたくさんあるということですね。一方、structはimmutableに物事を扱うことが可能、と。

class Temp {
    var c: Double = 0
}

class Country {
    var temp: Temp

    init(temp: Temp) {
        self.temp = temp
    }
}

let t = Temp()
t.c = 25
let c1 = Country(temp: t)
t.c = 40
let c2 = Country(temp: t)

c1.temp.c
c2.temp.c

そのため、クラスは何らかのライフサイクルに添いたいところや参照を共有する必要がある。

11章

OptionalとImplicitlyUnwrappedOptionalの使い分けの話。どう使うべきか、という話。
クロージャを使うときの、キャプチャリストと weak / unowned の違い、その使い分けも。

let closure = { [weak object1, unowned object2] () -> Void in
    print(object1)
    print(object2)
}

第11章の話の中では、いくつかのデザインパターンの説明も出て来た。これは通知をやり取りするための手法として。その中にObserverパターンがあった。

import Foundation

class Poster {
    static let notificationName = Notification.Name("SomeNotification")

    func post() {
        NotificationCenter.default.post(name: Notification.Name("a"), object: nil)
    }
}

class Observer {
    init() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleNotification(_:)),
            name: Notification.Name("a"),
            object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    @objc
    func handleNotification(_ notification: Notification) {
        print("I got a message")
    }
}

var observer = Observer()
let poster = Poster()
poster.post()

12章

非同期処理の話。GCD(Grand Central Dispatch)をSwiftから使う話とか。DispatchQueueの話。Foundationに含まれる Operationを使った話も。
ここら辺はやっぱり複雑なところになるので、中身を調べた上でなにかのライブラリに乗っかりたいですね。

13章

Resultによるエラー処理の話などだった。enumで定義した成功/エラーを switch を使って分けていく方法ですね。

enum Result<T, Error> {
    case success(T)
    case failure(Error)
}

Erlang/Elixirの {:ok, xxx}{:error, xxx} に対するパターンマッチなどん処理を思い浮かべました。
毎回 switch を書く必要もありますが、ここは将来パターンマッチ含まれるともっとErlang/Elixirに似た記述になりそうですね。

do-catchはまとめてエラー処理を描きたいときなど

エラー処理の選定

エラー処理を行う --no--> リリース時のプログラムの
    |                        終了を許容 ----no--> assert
   yes                             `----yes---> fatalError(_:)
    |
エラー処理の詳細が必要 ----------------------no--> Optional
    |
   yes
    |
同期処理 ----------------------------------no--> Result
    `------------------------------------yes-->  do-catch

まとめ

この書籍、やっぱり良いですね。Swiftに関して、言語仕様ではなく経験からどう使うと良いのか、という話がまとまっている。
これを読む/読まないで知識のつけ方が大きく変わりそう。

ありがとうございました。

[Swift][Elixir]implement chat server and client

Implement Chat Server with Phoenix and chat client with iOS application.

Server

After running the server, you can open chat page, http://localhost:4000/, via browser.
The server has no DB. So, history will be deleted if someone reload browser.

Client

Only join the room and send pre-set message to the server.
Don’t support display all chat message, store message and so on.

images

sample

[Swift]protocol、再び

Object Orientedではなく、Protocol Oriented(Swift)への理解を深めたい最近です。

https://www.raywenderlich.com/109156/introducing-protocol-oriented-programming-in-swift-2

の記事をざっと読みながら思ったのですが、protocolでは let の定義がつかえないことに疑問を覚えました。StackOverflowでも確かにありました。

http://stackoverflow.com/questions/34385897/why-i-cant-use-let-in-protocol-in-swift

protocolは抽象インタフェースになるので、具体的な値が入りません。letはconstantな振る舞いが必要ですが、protocol自体は具体的な値はその具体化されたstructやclass、enumなどで変化するためですね。なので、protocolでは var を使う必要があります。ただ、そのstructなどのprotocolを引き継ぐ時はその先で let を使ったりできます。

なるほどね。

ちなみに、以下がprotocolとそれを使ってstructやenum、extensionした簡単な例です。protocolで { set } を指定していると、当然ながらemutableではいられないので継承した先で同名の変数は let で定義することはできません。

extensionの書き方、 when Self: XXXX という感じて拡張する先を書くのですね。Elixirだとdefimplで for XXX みたいな感じで書いているところ。なるほど。

[iOS]EarlGreyを使ってシナリオを記述する

過去、 EarlGreyが出たての頃に試してみた のですが、最近またプライベートで使ってみたので自身のために残しておきます。

幾つかサンプルではなくて自分で使ってみて、Appiumとの使い分けやテストレベルの対応などもある程度私の中で腑に落ちた感じがしました。

EarlGreyについて

EarlGreyは、XCUITestみたいに描画要素に対して何らかの操作を行うライブラリです。面白いのは、 UIView をハックしてなにか操作を模倣するのではなく、 UIAccessibility Protocolを操作する。

リポジトリはこちら。

https://github.com/google/EarlGrey

EarlGrey自体の説明はあるのでここでは書きません。

何か困った時

使えるAPIや、使い方がわからないとか、そういう時はテストコード読んだりAPIドキュメント見るとある程度対応できます。

  • APIドキュメント
  • Matcherの実装
    – どのように動作しているか、といった説明も書かれているので、ざっと一読することをお勧めします
    https://github.com/google/EarlGrey/blob/master/EarlGrey/Matcher/GREYMatchers.h
    – AccessibilytLabelやidentifierの他にも、Valueなど多くの要素が使えるのよいですね
    – ただ、 We strongly recommend using an accessibility identifier as it uniquely identifies an element. と書かれているように、やぱり accessibilityIdentifier を使うことが良いことには変わりなさそう。ここは激しく同意。

Other Tips

  • 要素を見つけたい時
    • シミュレータだと、AccessibilityのAccessibility Inspectorを有効にしてそれを使うと良いです
    • Appiumだとinspectorを使ったりPonyDebugger使ってたのですが、このAccessibility Inspectorが実は一番楽なのかも?
  • Search Fieldなどで”Search”をしたい(テキスト入力後の決定)
    • \ngrey_typeText で入力しましょう。そこを契機にkeyboardの”return”や”search”になる箇所の操作と同じ動作をします

シナリオの記述例

以下、Searchフィールドをたっぷ、”KazuCocoa”と入力して決定、検索するというシナリオです。

  • selectElementWithMatcher で要素を見つけ、 performAction で何か操作をし、 assertWithMatcher で要素をチェックする。
  • EspressoのViewMatcher、Perform、Assertの形と同じですね。Googleではこういう形での記述に統一しているような雰囲気を得ます。

具体的には以下。

Appiumとの使い分け

ざっくりと書くと、ツールの使い分けは以下な感じ。Quickなどはありますが、やはりSwiftでシナリオベースのテストコードを書くのは面倒です。なので、本当にその視点から記述したシナリオベースのテストを残しておきたいなら、私はAppium + Rubyをベースにしたものをつかたいと思います。

  • Appiumを使うとき
    • シナリオを記述したテストコードの実行
    • ネットワークキャプチャなどのアプリ全体を操作したい時
  • EarlGreyを使いたい
    • CIに組み込む
    • 限定的な操作を安定して早く実施したい
      • イメージとしては、単一の機能であったり、境界値によってViewが変化するような隅っこのチェック
    • Layoutをチェックしたい(image diffではない)

image diffなんかは単なるassertionの手段なので、必要に応じて使いましょう。

こういうのを、社内で置いているテストレベルと照らし合わせながら導入できると雑多にはならなさそうですね。

XCTest -> EarlGrey -> Appium

という感じで、ロジックのチェックからGUIのチェック、アプリ全体の計測まで進んでいくと順当そう。
ちょうど、テストサイズをベースにするとS/M付近がXCTest、M/L付近がEarlGrey、L/EがAppiumという感じの関係性でしょうか。

締め

あまり情報がないですが、やはり短時間で成果を出すにはこの手のテストコードも素早く安定させた形にすることが必要です。その上で、この手ではできないことを人が実施する。

そのためにはこういうツールやテストの構築方法含め、フルで知見を導入していきたいですね。

[Swift]Regular Expression with Swift

Swiftのexercism.iosを解いている時に、正規表現を使いたい箇所に出くわしました。
Swift、ObjCのそれを使わないといけないのですね。私が扱う言語の中では一番手間隙がかかるやつでした。

メモメモ。以下は、入力文字列に対して 0-9 の数字を文字列として抜き出すメソッドです。

他、String(instance) として、 instance から値を取得できる CustomStringConvertible を使ったので合わせてメモ。

https://developer.apple.com/library/mac/documentation/Swift/Reference/Swift_CustomStringConvertible_Protocol/index.html

Swift、Appleの2.1向けの資料は読んでいたのですが、やっぱり巨大だ…

[iOS] test UI with google/EarlGrey

This morning, Google published a blog named EarlGrey – iOS Functional UI Testing Framework.

They also opened their UI Testing framework in the article.

https://github.com/google/EarlGrey

I tried a demo packaged in the repository.

https://github.com/google/EarlGrey/tree/master/Demo/EarlGreyExample

The framework looks using accessibility inspector . So, we can see the inspector on simulator when I run test. See the following.

スクリーンショット 2016-02-17 23.22.59

Hm…

If this library separate with production code completely, this library will be one of the cool framework for UI Test, I suppose.

(This framework support over iOS8.x. So, If you support iOS7, you can’t use the framework. See https://github.com/google/EarlGrey/blob/master/docs/backward-compatibility.md )

[Swift]UI Testing Failure – Multiple matches found

XCUITestでは、例えば以下のように記述することで、button要素に “example” とtitle/accessibilityIdentifierなどが付与されたものを取得、tapします。

func testTapButtons() {
    XCUIApplication().buttons["example"].tap()
}

ただし、表示されている画面要素に対して、この条件に合致する要素が複数存在した場合、以下のようにエラーが表示されてテストがこけます。

UI Testing Failure – Multiple matches found

こんな時は、以下のように elementBoundByIndex を使うことで、特定の配列要素を得ることができます。( childrenMatchingType(.Button) はオマケ )

func testTapButton() {
    XCUIApplication().childrenMatchingType(.Button). matchingIdentifier("example").elementBoundByIndex(0).tap()
}

例えば、Appium x ruby_libを使った場合は複数要素を取得する場合は配列で要素が得られます。なので、そこらへんを使ったことがある人だとSwiftでも配列として得られて、 XCUIApplication().buttons["example"][0].tap() とかでできそうな気がしますが、そでは正しく動作しません。 elementBoundByIndex を使わないといけないのですね。

なるほど。

ここら辺、ソースコードと睨めっこな領域になるのですが、だいぶどんな感じのメソッドがあるのか把握してきた感じ。

[Swift]XCUITestにおけるCoverageとScreenshotの在り処

XCUITestでは、自動的にスクリーンショットを取得してくれます。それがどこに保存されるか?というと、以下のように Attachments に保存されました。保存されるファイル名に統一感がないのですが、 plist にテストケースとスクショの結びつけを保存しているのですね。テスト結果をXcode以外からうまいこと見ることできないかなーと思ってたのですが、すんなりホイとはできなさそうな感じです。

/Users/user-name/Library/Developer/Xcode/DerivedData/TestProject-randome-values/Logs/Test/Attachments

あと、スクショのタイミングを任意なタイミングではできないので画像比較のためにそれを使う、というのには使えなさそうな感じです。んー。テスト失敗した時の参考になる以上ではちょっと使いにくい感じです。

ついでに、XCUITestでも、カバレッジを取得できる模様?ちゃんと計測はしていないのですが、うまいこと使えれば使えそうでした。

そのほか

XCUITest、いろいろ調べてみましたが通知のダイアログなどのシステム設定をリセットする手段ないので、ちょっとテストケースの管理に難しさを感じました。
ちなみに、wait/sleepは適度にwaitしてくれるので、さほど気にしすぎなくても良いのですね。 waitUntil のようなメソッドを定義したのですが、それを使うのは限定的になりそう。retryが内包されているのはGUIから操作するテストケースではありですね。Exceptionを出す種類も、 XCTAssert 系以外にもいくつかあったのですが、ここはXCTestの頃からそのまま使っているもののようですね。

このfastlaneのsnapshotも、このXcode7(XCUITest)対応したみたいですね。
https://github.com/fastlane/snapshot