テストコンテナとクリーンアーキテクチャ
概要
「外部世界」(DBMS、外部API、ウェブ)と通信する責任がある「ソフトウェアの一部」のような我々のシステムの境界を特定するために、ドメイン許可からの基盤を切り離すこと.TestContainer Technologyを解析し、システム境界のテストスイートを構築します.
からtest containers docsは次のようなテストを簡単に行うことを知っています.
型
この関数のためにDBアクセス層を書きたいと思います.
loadEmployees: () -> Either<Error, Employees>
私もDockerインフラストラクチャを使用してテストします.私はfileload社員関数のいくつかの統合テストがあることを覚えています.
@Test
internal fun loadSomeEmployees()
@Test
internal fun employeeNotValidEmail()
それらを記述するのを避けることができるように、彼らは全く明確です.DBの実装に使用したいのですが、テストコードを複製したくありません.私は両方の実装(ファイルとDB)に使用できるこれらのテストの抽象化を作成するつもりです.
abstract class LoadEmployeeTest {
@Test
internal fun loadEmployee() {
val loadEmployees = instance()
assertThat(loadEmployees()).isEqualTo(
Either.Right(
Employees(
listOf(
Employee(
"Marco", "Sabatini", DateOfBirth(5, 3, 1983),
EmailAddress("[email protected]")
)
)
)
)
)
}
@Test
internal fun employeeNotValid() {
val loadEmployees = wrongInstance()
assertThat(loadEmployees()).isEqualTo(Either.Left(Error("Error For input string: \"wrong\"")))
}
abstract fun instance(): () -> Either<Error, Employees>
abstract fun wrongInstance(): () -> Either<Error, Employees>
}
基本的に2つの抽象メソッドを実装します.これらのメソッドは、ハッピーパスとコーナーケースの相対関数の実装(ファイルまたはDB)を返さなければなりません.ファイルアクセス層には(タナaa !):
override fun instance(): () -> Either<Error, Employees> =
loadEmployeeFrom("./target/test-classes/employees.txt")
override fun wrongInstance(): () -> Either<Error, Employees> =
loadEmployeeFrom("./target/test-classes/employeesNotValid.txt")
@Test
internal fun fileNotFound() {
val loadEmployeeFromFile = loadEmployeeFrom("NOT_EXIXSTING_FILE")
Assertions.assertThat(loadEmployeeFromFile())
.isEqualTo(Either.Left(Error("File NOT_EXIXSTING_FILE doesn't exist")))
}
DB Access Layerのために、(タナaa !): @AfterEach
fun cleanupTest() {
execute("DELETE from employees")
}
override fun instance(): () -> Either<Error, Employees> {
execute("INSERT INTO employees VALUES ('Marco', 'Sabatini','05/03/1983','[email protected]')")
return loadEmployeeWith()
}
override fun wrongInstance(): () -> Either<Error, Employees> {
execute("INSERT INTO employees VALUES ('', '','wrong','')")
return loadEmployeeWith()
}
private fun execute(sql: String) {
val stmt = connection().createStatement()
stmt!!.executeUpdate(sql)
stmt.close()
}
この手法を呼ぶcontract test また、CodeBaseの特定の動作を定義しなければならない場合には非常に便利です.この場合、私は自分のドメインコードと私のインフラコードの間でロードワーカーの振る舞いを定義しました.これは非常に我々は外部のポートのメモリの実装にしたいと我々の受け入れテスト(超高速!
DockerとDockerの作成
今ではインフラの部分に移動する時間です.私は、DBMS MySQLインスタンスとJVM Mavenのランタイムが必要です.これらの容器は互いに通信しなければならない.
これは私が使用したDocker構成ファイルの設定です.
services:
mysql:
image: mysql
container_name: mysql_server
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=pwd
networks:
- db-network
db_client:
build:
context: ./containers/client
networks:
- db-network
environment:
- WAIT_HOSTS=mysql:3306
- WAIT_HOSTS_TIMEOUT=300
- WAIT_SLEEP_INTERVAL=30
- WAIT_HOST_CONNECT_TIMEOUT=30
maven:
image: maven
container_name: builder
volumes:
- ${PWD}:/tmp
networks:
- db-network
networks:
db-network:
MySQL : DBMS
DBRANクライアント:MySQLクライアントのコマンドラインインターフェイスです.スキーマを作成し、他の目的のために使用することができます.
SchemyPoint Dockerを使用してスキーマや読み込みデータを作成しますplugin MySQLインスタンスを待つのを助けます.
case "$@" in
schema)
/wait && mysql --host=mysql -uroot -ppwd < employees.sql
echo "EMPLOYEES schema created!"
;;
demo)
/wait && mysql --host=mysql -uroot -ppwd < demo.sql
echo "Could load demo data!"
;;
*)
exec "$@"
;;
esac
Here Dockerコンテナの設定の詳細を見ることができます.Maven :私のKotlinテストコードが実行されるコンテナです.
#!/bin/bash
docker-compose up -d mysql
docker-compose build db_client
docker-compose run db_client schema
docker-compose run maven mvn --quiet -f /tmp clean install
docker-compose run maven mvn -f /tmp surefire-report:report -DshowSuccess=false
docker-compose down --remove-orphans
コンピュータ上で直接実行するプロジェクトをビルドするか、CIパイプラインを作成するために使用できます.CIパイプラインの設定
私はGHのアクションを使用してgithubに私のCIを構築するためにすべての作品を持っている.
下.Github/フォルダにこの設定があります.
name: docker-compose-actions-workflow
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: CI
run: script/ci
- name: DEMO
run: script/demo
これは、押すと、CIとデモスクリプトを実行するビルドを開始します.下tab actions すべてのビルドを出力で見ることができます.
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.kata.testcontainers.infrastructure.DBLoadEmployeeTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.561 s - in com.kata.testcontainers.infrastructure.DBLoadEmployeeTest
[INFO] Running com.kata.testcontainers.infrastructure.FileLoadEmployeeTest
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 s - in com.kata.testcontainers.infrastructure.FileLoadEmployeeTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
containers ---
デモ出力:######## Employees ########
First Name: Marco
Last Name: Sabatini
Email: EmailAddress(value=[email protected])
BirthDay: DateOfBirth(day=5, month=3, year=1983)
....
私は念頭に置いて検証、パフォーマンスや品質のゲートステップを追加することができます考慮
プロジェクトCodeBaseの下にインフラストラクチャを持つことは、全体的な生態系を理解し、devと操作の間の距離をカットするのに役立ちます.このような状況では、コンテナのクラウドサービス(AWS上のEX . ECS)にコンテナを配備することができました.また、CIの中で見たり、デモを行ったりするのと同じように動作します.
もちろん、組織の観点から、これはまた、コードを開発することができて、必要な基盤を選んで、つくることができる人々を持つことを意味します.
開発者として我々はコードのIDE“ユーザー”またはシステムエンジニアだけについて考えていない!
参考文献
Reference
この問題について(テストコンテナとクリーンアーキテクチャ), 我々は、より多くの情報をここで見つけました https://dev.to/ticinoswcraft/tests-infrastructure-1gkoテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol