ScalaのUnitテストでDocker

 ScalaのUnitテストでDocker

キノコがDockerについて勉強する会
https://kinoko-hoge.connpass.com/event/88048/

サンプルコードはこちら。
https://github.com/yoshiyoshifujii/180623_using_docker_in_unit_test_of_scala

C952d9f90c7ec6cb1b5513c05d3db536?s=128

yoshiyoshifujii

June 30, 2018
Tweet

Transcript

  1. SCALA の SCALA の UNIT テスト UNIT テスト で でDOCKER

    DOCKER @yoshiyoshifujii 1
  2. こんにちは こんにちは Yoshitaka Fujii Software Engineer Scala / DDD /

    Microservices / Serverless / Agile @yoshiyoshifujii
  3. 2

  4. UNIT テスト UNIT テスト で毎回、苦労 で毎回、苦労 するところ するところ 3

  5. データベースを操作するプログラムのテスト Mock とかにしちゃいがち ElasticSearch Amazon Simple Queue Service 様々な外部サービス/ ミドルウェア

    4
  6. 開発のとき 開発のとき git clone して test ができない 環境構築手順書が必要(Windows 版、macOS 版…)

    動かないスクリプト 共通のサーバー 5
  7. DEPLOY のとき DEPLOY のとき Jenkins Slave に事前にインストール インストールできない場合は接続できるように 版が変わったらSlave の環境を更新

    職人の誕生 開発環境と別で対応する必要がある 開発環境と共存にすると、ルールでしばったり大変 6
  8. 理想 理想 Unit テスト実行したら環境できて欲しい 開発もCD/CI も実行したら環境できて欲しい git clone したら何も考えずに test

    実行したい 7
  9. DOCKER ならできそう DOCKER ならできそう docker コマンドを実行したらimage 取れるし docker コマンドを実行したら環境できるし Unit

    テストのbefore/after でなんとかなりそう 8
  10. 探したらあっ 探したらあっ た た whisklabs/docker-it-scala 9

  11. SETUP SETUP libraryDependencies ++= Seq( "com.whisk" %% "docker-testkit-scalatest" % "0.9.5"

    % "test", "com.whisk" %% "docker-testkit-impl-spotify" % "0.9.5" % "test" ) 10
  12. ちなみに… ちなみに… は、 は、 に に 依存しています。 依存しています。 は、Java ライブラリなので、こ

    は、Java ライブラリなので、こ れを使ってうまいことやれば、Java で出来る。 れを使ってうまいことやれば、Java で出来る。 ( はずです。試してません…) ( はずです。試してません…) whisklabs/docker-it-scala whisklabs/docker-it-scala spotify/docker-client spotify/docker-client spotify/docker-client spotify/docker-client 11
  13. 今回はDynamoDB で試してみた 今回はDynamoDB で試してみた libraryDependencies ++= Seq( "com.amazonaws" % "aws-java-sdk-dynamodb"

    % "1.11.353" ) 12
  14. DockerSpecSupport.scala DockerSpecSupport.scala Spotify のDocker Client を使って Spotify のDocker Client を使って

    docker を操作する基底となる処理を書く。 docker を操作する基底となる処理を書く。 trait DockerSpecSupport extends DockerTestKit { this: Suite => private val dockerClient: DockerClient = DefaultDockerClient.fromEnv().build() override implicit def dockerFactory: DockerFactory = new SpotifyDockerFactory(dockerClient) } 13
  15. DockerDynamoDBSpecSupport.scala DockerDynamoDBSpecSupport.scala trait DockerDynamoDBSpecSupport extends DockerSpecSupport { this: protected val

    dynamoDBPort = RandomSocket.nextPort() protected val dynamoDBContainer = DockerContainer("fingershock/dynamodb-local:latest") .withPorts(8000 -> Some(dynamoDBPort)) protected val dynamoDBClient: AmazonDynamoDB = AmazonDynamoDBClientBuilder.standard() .withEndpointConfiguration( new EndpointConfiguration( s"http://127.0.0.1:$dynamoDBPort", Regions.AP_NORTHEAST_ )).build() } 14
  16. DynamoDBSpec.scala DynamoDBSpec.scala class DynamoDBSpec extends FlatSpec with Matchers with DockerDynam

    private val TableName: String = "sample-table" override def dockerContainers: List[DockerContainer] = dynamoDBContainer :: super.dockerContainers override def beforeAll(): Unit = { ... } override def afterAll(): Unit = { ... } "DynamoDB" should "success" in { ... } } 15
  17. DynamoDBSpec.scala #beforeAll DynamoDBSpec.scala #beforeAll override def beforeAll(): Unit = {

    super.beforeAll() val createTableRequest = new CreateTableRequest() .withTableName(TableName) .withAttributeDefinitions( new AttributeDefinition("id", ScalarAttributeType.S)) .withKeySchema( new KeySchemaElement("id", KeyType.HASH)) .withProvisionedThroughput( new ProvisionedThroughput(1L, 1L)) dynamoDBClient.createTable(createTableRequest) } 16
  18. DynamoDBSpec.scala #afterAll DynamoDBSpec.scala #afterAll override def afterAll(): Unit = {

    dynamoDBClient.deleteTable(TableName) super.afterAll() } 17
  19. DynamoDBSpec.scala #DynamoDB should success DynamoDBSpec.scala #DynamoDB should success "DynamoDB" should

    "success" in { dynamoDBClient.putItem( TableName, Map( "id" -> new AttributeValue().withS("aaaaa") ).asJava ).getAttributes shouldBe null dynamoDBClient.getItem( TableName, Map( "id" -> new AttributeValue().withS("aaaaa") ).asJava ).getItem.asScala("id").getS shouldBe "aaaaa" } 18
  20. run run 21:31:58.171 [pool-5-thread-1] DEBUG com.spotify.docker.client.Do 21:31:59.184 [pool-5-thread-1] DEBUG com.spotify.docker.client.Do

    21:32:01.330 [pool-7-thread-1] DEBUG com.spotify.docker.client.au java.lang.IllegalArgumentException: serverAddress=https://index.d at com.spotify.docker.client.DockerConfigReader.parseDock at com.spotify.docker.client.DockerConfigReader.fromConfi at com.spotify.docker.client.auth.ConfigFileRegistryAuthSu at com.spotify.docker.client.DefaultDockerClient.pull(Def at com.spotify.docker.client.DefaultDockerClient.pull(Def at com.whisk.docker.impl.spotify.SpotifyDockerCommandExecu at com.whisk.docker.impl.spotify.SpotifyDockerCommandExecu at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0 at scala.concurrent.Future$.$anonfun$apply$1(Future.scala at scala.concurrent.Future$$$Lambda$3750/1704912779.apply at scala.util.Success.$anonfun$map$1(Try.scala:251) at scala util Success map(Try scala:209) 19
  21. まとめ まとめ を使えば、 を使えば、 Unit テストからDocker Image を実行できる。 Unit テストからDocker

    Image を実行できる。 は、Java ライブラリなので、 は、Java ライブラリなので、 きっと同じことできる。 きっと同じことできる。 git clone したら test がすぐできる。 git clone したら test がすぐできる。 CD/CI のときも、環境作らなくて良い。 CD/CI のときも、環境作らなくて良い。 サンプルコードは、 サンプルコードは、 whisklabs/docker-it-scala whisklabs/docker-it-scala spotify/docker-client spotify/docker-client yoshiyoshifujii/180623_using_docker_in_unit_test_of yoshiyoshifujii/180623_using_docker_in_unit_test_of 20
  22. 以上です 以上です 21