196の日記

完全に開発メモと雑談、その他忘れそうな計算式などを書き溜める場所になっています!

雑談 日記〜インターンとりあえず一ヶ月通って思ったこと〜

ただの日記だよ。最初の投稿以来のただの日記かもしれない。

率直に感じたこと

スキルがやばいほど身につく

これ。書いてる言語(scalaは初めてだったから余計知識が増えた)だけでなく、gitやslackなどを実践で使用するため、必然的に感覚で使えるようなスキルが身につくのは素晴らしい!本当に!

その現場固有の技術

便利に使いやすくなっているのは素晴らしいことだけれど、学ぶ立場からすれば、その便利になっている部分は省略されているのと同等で、そこは学べないし他の現場に行ったらまた覚え直しだったりもする。技術を学びに行っている立場を踏まえて柔軟に知識を吸収したいところ。

社内雰囲気

勝手に伝わってくる。職業体験ではないけれど、面接や紹介だけで訪れるだけでは決して見えない部分も見える。結構面白い。

気が楽

立場的に弱いけれどその文責任も少ない。気負いなく生活しながら勉強し、職場に居られるもは非常にありがたい環境だと感じた。

これから

何よりも、今回のインターンの最終目的は、クライアント側とサーバ側のつなぎ目の技術を習得すること及びサーバ側の実装を知ることなので、そこを忘れないようにしたい。

scalatest Mockテスト

playframeworkでのモックテストを実装することになって色々わからなくて苦しんだのでメモ。

そもそも

DI(依存性の注入)をしっかり意識して実装しないと、ユニットテストが行いにくい(ユニットテストのためにIDを意識すると言っても大丈夫なくらい)

モックオブジェクト

モックオブジェクトを作ることで、テストを行いたいメソッド内の不必要な処理を置き換えることが可能。

テストクラス

ユーザとメールアドレスを紐付けるUserMailLinkerをテストするクラスを作る。MockitoSugerを使用することでMockオブジェクトを作成可能に。

class UserMailLinkerTest extends FlatSpec with Matchers with MockitoSugar

今回はUserMailLinker内に実装した以下のメソッドをテスト(正確にはUserMailLinkerはtraitとなっており、それをextendsする形でUserMailLinkerImplクラスを実装、その中にこのメソッドを定義している)。メソッド内のloginMailDALはデータベースにアクセスする感じのメソッドが格納されている。メソッド外クラス内に変数として定義されている。

val loginMailDAL = new LoginMailDAL() //ちょっと雑に書いたのでここ違うかも。とにかく、変数として実装しておくのがミソ
override def checkEmailExist(email: String) = {
    loginMailDAL.getUserByEmail(email).map(_ match {
      case Some(user) =>{
        logger.info(s"Email:${user.email} is already exist")
        true
      }
      case None => false
    })
  }

このメソッドをテストするには、loginMailDALの結果を明確にこちらで操作できると都合が良い。同時に、テストするときにDBにアクセスするのは良くないし、依存がどーのこーのとID面から見てもよろしくない。そこで、使用するのがモックオブジェクト。UserMailLinkerTest内に以下のように実装する。

  val mockLoginMailDal:LoginMailDAL = mock[LoginMailDAL]
  val linker = new UserMailLinkerImpl(){
       override val loginMail = mockLoginMailDal
 }

これまた少し雑に書いたけれど、こんな感じで、モックオブジェクトを生成してそれでloginMail内の変数を上書きしてしまうという技。後は上書きに使用した、mockLoginMailDal内のメソッドを弄ってやると、うまくテストが可能。loginMailDal内のgetUserByEmail(email:String)を書き換えるには、UserMailLinkerTest内に以下の文を追加。

Mockito.when(mockLoginMailDal.getUserByEmail("email@exist.com")).thenReturn(loginMail) //loginMailはユーザ情報を保持する

これで、先ほど生成したモックオブジェクトが持つgetUserByEmail()は、”email@exist.com”という文字列を受け取ったら他の処理は何もせずに、ただloginMailをリターンするだけのメソッドになる。こうすることで、UserMailLinker内のcheckEmailExist()に実装されているものも上書きされ、メソッドのテストのみに集中できる。

/** 既に登録してあるアドレスならtrueが帰ってくる */
  "checkEmailExist" should "check Email is Already Registered" in {
    val f:Future[Boolean] = linker.checkEmailExist("email@exist.com").run()
    ScalaFutures.whenReady(f){ f=>
      assert(f == true)
    }
  }

ちなみに、例外をthrowするものをテストしたい場合はintercept[T]()を使用する。これを使わないと意図させて起こした例外も、結局ただの実行中に起こったエラーとして扱われてしまう。以下は、メアドとパスワードが違った場合、エラーを投げるgetLoginMailByEmailAndPassword()メソッドをテストしている。

"getLoginMailByEmailAndPassword" should "Error by incorrect information" in{
    intercept[Exception]( linker.getLoginMailByEmailAndPassword("email@nonExist.com", "Password1").run())
  }
||

追記 2/28
上の例外テストはあまりよろしくないかも。
>|scala|
val incorrectE = linker.getLoginMailByEmailAndPassword("email@nonExist.com", "Password1").run()
    ScalaFutures.whenReady(incorrectE.failed){ e => assert(e == 予想されるexception系のもの) }

incorrectEはFuture型を保持するとなり、その中に投げられたエラーが包まれている感じになってる。なので、その中身を取り出してパワーアサートで比較してあげるのがいいはず。

ユニットテスト

ユニットテスト

www.techmatrix.co.jp


単体テストユニットテスト)は、プログラムを構成する比較的小さな単位(ユニット)が個々の機能を正しく果たしているかどうかを検証するテスト。関数やメソッドがそのテストの対象となる。プログラムが全体として正しく動作しているかを検証する結合テストより断然早い段階で行われる。

利点

実装時にテストを行うため、問題の特定や修正が容易になる。
実装した人がその直後におそらくテストケースを実装するため、妥当性の高いテストケースを残せる。

欠点

実装者に負担。
実装者自身にもある程度の知識が要求される。
当然時間を取られる。また時間の関係でテストが省かれた場合、プロジェクト全体でテストが省略されたり実装されてたりと、バラバラになる可能性がある。

種類

ホワイトボックステスト
テスト対象のメソッドor関数の内部に着目。条件分岐や繰り返しなどの各部分を確実にテストする。

ブラックボックステスト
テスト対象のメソッドor関数の入出力に着目。期待する機能を満たしているかをテストする。

Dependency Injection 依存性の注入

まずここで概念を掴んで
qiita.com


このページでもう少し掘り下げると、すんなりと概要が頭に入ってきます。
itpro.nikkeibp.co.jp

ざっと掴んだ感じ、、

Aが必要とするBというものを、A内に含めずに、実行時に動的にAをBに渡そうという思考(多分)
似た挙動をAで使用する時、渡すものをBではなくCにすれば動くようにしておけば、実装も楽だしどこを変更すれば良いかもわかりやすく、なおかつ使い回しも可能でいいよねって感じ?(使い回しは副産物で、使いまわせるぐらい機能が分離されていてメンテナンスを含めて使用が行いやすいってことかな)

IDのメリットデメリット

コードが簡潔になり開発期間が短くなる <-> スタートアップ時のコード量(仕事量)が増える
階層構造が綺麗に分離された状態になる <-> クラスやファイルがたくさん生成される
特定のフレームワークへの依存が少なくなるため、柔軟になる

git 随分前にforkしたローカルリポジトリをfork元の最新の状態に更新する

blog.local-c.com

qiita.com

      • 追記 2017/3/29---

このサイト様がわかりやすかったです。
【備忘録】Fork元の変更を自分のリポジトリに反映する - 『入る学科間違えた高専生』の日記