/var/log/jsoizo

メモ帳 技術とか趣味とか

個人的に好きなKotestのmatcherたち 〜JUnitやkotlin.testでも使えるよ〜

この記事は検索エンジンプロダクトを一緒に開発してた同窓会 Advent Calendar 2023 の3日目。の代打です。 第二子出産に立ち会うまでのもどかしい待ち時間で心を落ち着けるために書いている。日本語がぐっちゃぐちゃかもしれない。 さて、現在の仕事ではKotl…

ジェネリクスを含む関数を関数オブジェクトとして扱いたい

このようなジェネリクスがある関数やクラスがあるものとする。 fun <T> foo(): T = TODO() class Bar<T> (val value: T) これらの関数やクラスのコンストラクタを関数オブジェクトとして扱いたいとき、このように :: を付与して KFunction1<T> のような値を宣言したい</t></t></t>…

KotlinでPartialFunctionを実装しcollect, collectFirstしたい

Scalaでいうcollect的な関数がほしいことがあって、このような関数を実装してみた。 fun <A, B> List<A>.collect(vararg patterns: Pair<(A) -> Boolean, (A) -> B>): List<B> = this.mapNotNull { a -> patterns.firstOrNull { (condition, _) -> condition(a) }?.let {</b></a></a,>…

buildpackでビルドしたSpring BootコンテナのHTTPヘルスチェック

composeしてたりECS使ってるとサービスディスカバリしたりblue/greenデプロイをするための前提としてコンテナのヘルスチェックを行うことが多い。 個人的には、デプロイ成否の条件にも使えたりするので、webサーバなどコンテナでデーモンを実行するときはヘ…

Playwright Javaをマルチスレッド環境下で平行に動かす(Kotlinで)

注: これが正解かはわかっていない 一度にいくつかのe2eテストを高速に実行する目的で並列にしたくて、かつブラウザのコンテキストつまりCookieなどをテスト間で共有したくない場合がある。 たとえば、並列実行したい2つのテストがそれぞれwebサービスのログ…

KotlinでMinimal Cake Pattern

出来そうだなと思ったのでお試し。 Minimal Cake PatternといえばScalaにおけるDIの実装パターンの1つで、コンパイル時に依存性を解決でき、DIコンテナ使ってるときにやりがちなDI用アノテーションのつけ忘れて実行時エラーが起きるみたいなことが無いのが特…

Viteはライブラリモードの時にアセットを自動的にbase64エンコードしてくれる

たとえばコンポーネントライブラリを作ろうとしていて、そのコンポーネント内で特定の画像ファイルをbackground-imageで埋め込みたいというケースを考える。 このとき、画像をどうやってパッケージに含めるか、とか、ライブラリ利用側でのパス解決がうまいこ…

コンストラクタの返却する型を変えたいときのcompanion object + invoke()パターン

こういうクラスがあり、newする時にエラー型を明示して Either<IllegalArgumentException, Email> が返却されるようにしたいとする。 class Email(val address: String) { init { require(address.contains("@")) { "Invalid email address" } } } とすると、このように書くことが多いのだが、</illegalargumentexception,>…

KotestでTable Driven Testする

KotestでTable Driven Testをサポートしているシンタックスがあるのでそれを使えば良い。 JUnitでもやっている例はあるけど、Kotestの方がデータ型の用意が不要だったりするのと、テストの可読性が高そうにみえる(好みの範疇)。 また、Table Drivenにテスト…

Kotlinで部分適用するためのExtension

部分適用するために以下のようなExtensionを用意しておくと便利。 fun <A, B, C, T> Function3<A, B, C, T>.partial(a: A): (B, C) -> T = {b, c -> invoke(a, b, c)} 例えば以下のような引数を3つ取る関数の場合だとこのようになる。 fun example(foo: Int, bar: String, baz: Long)</a,></a,>…

(翻訳) Kotlinでの型付きエラー処理

この記事は以下のブログの翻訳記事で、著者の許諾のもと翻訳しています。翻訳過程で機械翻訳を活用しており、原典と翻訳を十分に照らし合わせて内容が正しいことを確認しておりますが、細かいニュアンスなどが気になる場合は原典をご確認ください。また、誤…

複数のバリデーション結果を蓄積したいときのEither<Nel<E>, A>とzipOrAccumurate

よくあるケースとして、入力値に対してバリデーションを行いすべて評価してから結果を返したい場合がある。 たとえばこのようなPerson型があったときに、 class Person private constructor(val name: Name, val age: Age) ① name は空文字を許さない ② age …

Arrow.ktのnullable DSLでjOOQがnullable大量に生み出すのを何とかする

過去にjOOQのRecord型から値を取り出すときに、一旦nullableをArrow.ktのOption型に変換してから合成すると良いよ的な書き方をしたんだけど、 jsoizo.hatenablog.com 同じくArrow.ktのnullable DSLでもっとスッキリ書けるとわかったので改めて。 以下のよう…

Context Receiverを利用した簡易的なDI

Kotlin Confがはじまった!!! キーノートではKotlin 2.0に追加される言語仕様が発表された。 blog.jetbrains.com 個人的には好きなKEEP段階の機能であるContext Receiverがついに正式なリリースを迎えることになりそうで嬉しい一方で、Kotlin 2.0まで待たない…

Itelable<T>のfoldとrunningFoldの違い

よくつかっているIterableの自作extensionを紹介します - Speaker Deck で以下のようなコードを紹介した。 fun <A, F, S> Iterable<T>.partitionMap( predicate: (A) -> Boolean, transformFirst: (A) -> F, transformSecond: (A) -> S ): Pair<List<F>, List<S>> = this.fold(Pair(</s></list<f></t></a,>…

Arrow.ktにpartitionMapを追加するPRを出してコミュニティの暖かさに包まれた話

社内でラップバトル的な感じで情報共有をする会があるのだが、その場で "ScalaのpartitionMapがKotlinのIterableにはなくて不便だからextension書いた" 的な話をした。 反応も多少あったので調子に乗ってArrow-ktにissue切ってPRだしたら無事に取り込まれた…

Iterable<T>.firstNotNullOfOrNullはぱっとみよくわからないけどとても便利

scalaでいうcollectFirst的なやつが欲しいなーと思っていたところ、 firstNotNullOfOrNullっていうやーつがメソッド名だけ読んで理解するのが困難だがcollectFirst的に使えて便利だったのでメモ。 シグネチャは以下通り public inline fun <T, R : Any> Iterable<T>.firstNo</t></t,>…

jOOQのRecordから値を取得するときのnullableをarrowのoptionで綺麗に取り扱う

jOOQの Record.get(field) は以下のようなシグネチャでnullableである。 <T> T get(Field<T> field) throws IllegalArgumentException; nullableな処理が一つなら良いが、複数フィールドを取得したい場合などは以下のようなコードを書くことがある。 TODOS テーブ</t></t>…

Arrow Coreのデータ型探訪

これは Kotlin Advent Calendar 2022 の19日目が空いていたので書いたものです。 Kotlin中心の仕事になるので少しずつお勉強中なのだが、Scalaでコードを書いているときに使っている便利なデータ型が意外とKotlinにはないなとかNull-Safetyの方針がScalaとは…

AWS JDBC Driver for MySQLをslick経由で使いたい

前回、AWS JDBC Driver for MySQLの検証を行ったが、実際にはそのままJDBCドライバを使うということはなく、scalaなアプリケーションで使いたいときにはslickから呼び出すことが多いと思われる。 また、AWS JDBC Driver for MySQLはコネクションプールとして…

AWS JDBC Driver for MySQLのfailover機能に関する動作検証

これは スタンバイアドベントカレンダーの9日目です。 はじめに Amazon Aurora for MySQLでクラスタを組んでいて、可用性を高めるために書き込み可能インスタンスを複数並べてActive/Standby構成にすることがある。 このような運用をしているとき、Activeな…

Macのマイクミュート/アンミュートを制御したい

隣の部屋のベイビーや、ベイビーをあやすママの声がビデオ会議に入って来てしまうような問題がったのでマイクのmute/unmuteをトグルしたいなーとおもった。かつキーボードショートカットでいい感じにやりたい。 最終的にはここに書いたものは使っていない。 …

SlickでMySQLのIO周りを実装したときのユニットテスト

このあたりをいい感じに書けるとMySQL周りのユニットテストが簡易にできるので、 MySQLの実行環境の用意 DDLの適用 それぞれについて書きつつ、最終的にサンプルを示す。 なおtestcontainersを使ってこのへんを一気にやってしまうということもできるが、コン…

Amazon RDS(Aurora含む)のslowqueryログをpt-query-digestにかけたい

基本的には↓に書いてある方法でOKだが,ログをDLするときに一工夫必要。 www.percona.com 2022年04月現在、RDSの slowquery/mysql-slowquery.log はJSON形式で出力されるのでパースしてログ形式を変える必要がある。要はjqで必要なところだけ取り出せば良いと…

RedisまわりのUTを書きたかったらjedis-mockがべんり

タイトルの通り。 redisアクセスするScalaコードのユニットテストでつかって便利だった。 github.com wiremockみたいにredisのプロトコルをモックしてくれるやつ。 使い方 READMEに書いてあるとおりで特に詰まることはない。 以下はscalatestから呼び出すサ…

localstackを使って開発するときのテクニック

awsのPaaSを使う開発をしたいときにローカルでの開発環境構築やCI等のために localstack を使うことが多いのでメモがてらミニマムな設定を書いておく。 やりたいこと インストールや手動でのコマンド実行無しで必要な環境が構築できること ローカルPCやCIな…

scala.collection.immutable.SetOpts, scala.collection.SetOptsのメソッドツアー

前の記事でsubsetsの挙動を確認したついでに、collectionの中でもSet固有に実装されているメソッドを一通り叩いてみる。 特に明示しない場合このようなSet[Int]に対して叩くものとする。 val set = Set(1,2,3)

Set[T]から取りうるすべての組み合わせを生成するにはsubsets

タイトルの通り。 scala> Set(1,2,3) val res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3) scala> res0.subsets().toList val res1: List[scala.collection.immutable.Set[Int]] = List(Set(), Set(1), Set(2), Set(3), Set(1, 2), Set(1, 3), Se…

ScalaTestのAsync Specで複数のassertをしたい

こういうAsyncなテストがあり複数assertしたかったりする。 given-when-then-andのand相当。 class FooSpec extends AsyncFunSpec with Matchers { it("awesome test") { val f1: Future[String] = Future { Thread.sleep(1000) "foo" } val f2: Future[Stri…

Try,Option,EitherのorElse

Pull Requestでレビューをしていてこういう実装を見かけた。 fooで失敗したらbar, barで失敗したらbazを呼び出したい。 def foo(s: String): String = ??? def bar(s: String): String = ??? def baz(s: String): String = ??? val input: String = "awesome…