読者です 読者をやめる 読者になる 読者になる

XCTestを使ってみた

今までxcodeでtestを書いたことがなかったので、書いてみたいと思います。

xcode5から導入されたXCTestを使用してみます。

testって何とか、testって何で必要なのって方はこちらの記事が参考になります。 (予定がないのでiOSにおけるユニットテストについてまとめる その1

今回はprojectを作成するとデフォルトで生成されるtestファイルにtestを書いていきたいと思います。

まず、その前にtestの対象となるclassを実装しましょう。

今回はCalculation.swiftというclassを作って、その中に引数が偶数かどうかを判定するisEven()メソッドと2つの引数の和を返すsum()メソッドを実装しました。

import UIKit


class Calculation: NSObject {
    func isEven(dividedNumber: Int) -> Bool {
        if dividedNumber % 2 == 0 {
            return true
        } else {
            return false
        }
    }
    
    func sum(num1: Int, num2: Int) -> Int {
        return num1 + num2
    }
}

classを作れたら、testファイルがそのclassを参照できるようにShow the file inspectorのTarget Membershipのtestファイルのところにチェックを入れます f:id:icchii0618:20160104223543p:plain

続いてtestを実装して行きましょう。

今回はデフォルトの[project名]Testsファイルを利用します。 [project名]Testsの中のtestExample()にisEven()メソッドのtestを書いてみました。 さらに新しくtestを追加してみたりしました。

func testExample() {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
        
    XCTAssertTrue(Calculation().isEven(2), "偶数だとtrueが返ってきます")
    XCTAssertTrue(Calculation().isEven(4), "偶数だとtrueが返ってきます")
}
    
func testSum() {
    XCTAssertEqual(Calculation().sum(1, num2: 1), 2, "num1とnum2の和が返ってきます")
}

testはcmd + u か下記の画像の様にShow the test navigatorから実行します。 f:id:icchii0618:20160104225050g:plain

testをコケさせてみます。

func testExample() {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
        
    XCTAssertTrue(Calculation().isEven(2), "偶数だとtrueが返ってきます")
    XCTAssertTrue(Calculation().isEven(3), "偶数だとtrueが返ってきます")
}
    
func testSum() {
    XCTAssertEqual(Calculation().sum(1, num2: 1), 3, "num1とnum2の和が返ってきます")
}

3は偶数ではありませんし、1+1=3ではありません。

testがコケるとこんな感じでエラーが出ます。 f:id:icchii0618:20160104225242g:plain

testを意識しながらコードを書くと関数を良い感じに分けて書けると思いました。

RxSwiftを試してみた

最近話題のRxSwiftで残り文字数が表示されるTextFieldを実装してみました。

 

普通に実装すると少し面倒くさいらしいです。(iOS で文字数制限つきのテキストフィールドをちゃんと作るのは難しいという話 - blog.niw.at

 

f:id:icchii0618:20151228233228g:plain

 

また、「RxはFRPを実現するもの」だとか 「LINQのシーケンス処理をベースに、非同期イベント処理のリアクティブな記述をpush-base、pull-baseの両面からサポートするもの」だとかググれば色々な説明が出てきますがRxがどんなものなのかという個人的な見解はまた別のエントリで紹介できればと思います。

それでは実装に移りたいと思います。

まず、cocoa podsでRxSwiftとRxCocoaをインストールします

pod 'RxSwift', '~>2.0.0-beta'
pod 'RxCocoa', '~>2.0.0-beta'

こんな感じで必要なものをimportしたり定義したりして、

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {

    @IBOutlet weak var countLabel: UILabel!
    @IBOutlet weak var textField: UITextField!
    
    let disposeBag = DisposeBag()
    let maxStringCount = 30
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        countLabel.text = "残り\(maxStringCount)文字"
        self.subscribe()
    }

これが残り文字数を反映させるfunctionです

private func subscribe() {
        
    self.textField.rx_text
    .map { text in
        text.utf16.count
    }
    .subscribeNext{ textCount in
        self.countLabel.text = "残り\(self.maxStringCount - textCount)文字"
    }
    .addDisposableTo(disposeBag)
    
}

  本来なら面倒な実装を宣言的に少ないコードで書けている気がしますね。