-
Notifications
You must be signed in to change notification settings - Fork 71
[쇼핑 주문 3, 4단계] 공백 미션 제출합니다. #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 57 commits
01d94bc
321781d
a1934bc
f0d5393
cfaa6d0
11a2139
88c6daa
a20a756
6fd744e
7d04bdd
461f61d
cb6eb3d
56ccd2a
ca11a16
549fe17
f722bc6
93a5e60
3f109af
3c014ef
1b45551
076d16c
2cf4942
d68a7b3
0f054e4
2d5477a
f934066
e61c077
6d6bd5a
ec96f89
3c32906
9813c99
d032bd5
091dfea
6e00386
597f66c
cd81d48
3b853c5
8b99ed3
0a1ef45
5753097
c065dea
5cdf22a
2d01081
60f2750
fa9f5b7
0eb4fd9
a93e498
efc90fa
ee5aead
284a0c3
6e5c4a0
1f097c2
30d53a7
2496442
1657bc6
c5a7519
9616287
6d9e455
44f15b7
b173040
99bc4f2
3063b27
2f35dbe
ebdf561
a3fe4ac
ac19953
3561772
5ddd01f
cac48bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,13 +4,19 @@ import android.content.Context | |
import androidx.room.Room | ||
import androidx.test.core.app.ApplicationProvider | ||
import com.google.common.truth.Truth.assertThat | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.runTest | ||
import org.junit.After | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.jupiter.api.extension.ExtendWith | ||
import woowacourse.shopping.DUMMY_HISTORY_PRODUCT_1 | ||
import woowacourse.shopping.DUMMY_HISTORY_PRODUCT_2 | ||
import woowacourse.shopping.data.database.ShoppingDatabase | ||
import woowacourse.shopping.util.CoroutinesTestExtension | ||
|
||
@ExperimentalCoroutinesApi | ||
@ExtendWith(CoroutinesTestExtension::class) | ||
@Suppress("ktlint:standard:function-naming") | ||
class HistoryDaoTest { | ||
private lateinit var database: ShoppingDatabase | ||
|
@@ -28,108 +34,114 @@ class HistoryDaoTest { | |
} | ||
|
||
@Test | ||
fun 검색_기록을_저장하고_조회한다() { | ||
// given | ||
val historyProduct = DUMMY_HISTORY_PRODUCT_1 | ||
dao.insertHistory(historyProduct) | ||
|
||
// when | ||
val result = dao.getHistoryProducts() | ||
|
||
// then | ||
assertThat(result).hasSize(1) | ||
assertThat(result[0].productId).isEqualTo(DUMMY_HISTORY_PRODUCT_1.productId) | ||
} | ||
fun 검색_기록을_저장하고_조회한다() = | ||
runTest { | ||
// given | ||
Comment on lines
-42
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. runTest를 활용한 코루틴 테스트 아주 좋네요~ 이전에 마이그레이션 하다가 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
공식문서는 다음과 같이 명시하고 있습니다.
테스트만을 위한 싱글 스레드에서 작업을 진행하나보네요! public fun runTest(
context: CoroutineContext = EmptyCoroutineContext,
timeout: Duration = DEFAULT_TIMEOUT.getOrThrow(),
testBody: suspend TestScope.() -> Unit
): TestResult {
check(context[RunningInRunTest] == null) {
"Calls to `runTest` can't be nested. Please read the docs on `TestResult` for details."
}
return TestScope(context + RunningInRunTest).runTest(timeout, testBody)
} 위와 같이 context도 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
혹시 이 내용이 어떤 내용인지 좀 더 설명이 가능할까요~? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 하나를 말씀드리면, 열에 대한 내용을 알아오시는군요👍 |
||
val historyProduct = DUMMY_HISTORY_PRODUCT_1 | ||
dao.insertHistory(historyProduct) | ||
|
||
// when | ||
val result = dao.getHistoryProducts() | ||
|
||
// then | ||
assertThat(result).hasSize(1) | ||
assertThat(result[0].productId).isEqualTo(DUMMY_HISTORY_PRODUCT_1.productId) | ||
} | ||
|
||
@Test | ||
fun 검색_기록을_최신순으로_조회한다() { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1.copy(timestamp = 1)) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2.copy(timestamp = 0)) | ||
|
||
// when | ||
val result = dao.getHistoryProducts() | ||
|
||
// then | ||
assertThat( | ||
result.map { it.productId }, | ||
).containsExactly(DUMMY_HISTORY_PRODUCT_1.productId, DUMMY_HISTORY_PRODUCT_2.productId).inOrder() | ||
} | ||
fun 검색_기록을_최신순으로_조회한다() = | ||
runTest { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1.copy(timestamp = 1)) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2.copy(timestamp = 0)) | ||
|
||
// when | ||
val result = dao.getHistoryProducts() | ||
|
||
// then | ||
assertThat( | ||
result.map { it.productId }, | ||
).containsExactly(DUMMY_HISTORY_PRODUCT_1.productId, DUMMY_HISTORY_PRODUCT_2.productId).inOrder() | ||
} | ||
|
||
@Test | ||
fun 검색_기록이_제한을_초과하면_오래된_기록부터_삭제된다() { | ||
// given | ||
repeat(5) { index -> | ||
dao.insertHistory( | ||
DUMMY_HISTORY_PRODUCT_1.copy( | ||
productId = index.toLong(), | ||
timestamp = index.toLong(), | ||
), | ||
fun 검색_기록이_제한을_초과하면_오래된_기록부터_삭제된다() = | ||
runTest { | ||
// given | ||
repeat(5) { index -> | ||
dao.insertHistory( | ||
DUMMY_HISTORY_PRODUCT_1.copy( | ||
productId = index.toLong(), | ||
timestamp = index.toLong(), | ||
), | ||
) | ||
} | ||
|
||
// when | ||
dao.insertHistoryWithLimit( | ||
history = DUMMY_HISTORY_PRODUCT_2, | ||
limit = 5, | ||
) | ||
} | ||
|
||
// when | ||
dao.insertHistoryWithLimit( | ||
history = DUMMY_HISTORY_PRODUCT_2, | ||
limit = 5, | ||
) | ||
|
||
// then | ||
val result = dao.getHistoryProducts() | ||
assertThat(result).hasSize(5) | ||
assertThat(result.any { it.productId == 0L }).isFalse() | ||
assertThat(result.first().productId).isEqualTo(DUMMY_HISTORY_PRODUCT_2.productId) | ||
} | ||
// then | ||
val result = dao.getHistoryProducts() | ||
assertThat(result).hasSize(5) | ||
assertThat(result.any { it.productId == 0L }).isFalse() | ||
assertThat(result.first().productId).isEqualTo(DUMMY_HISTORY_PRODUCT_2.productId) | ||
} | ||
|
||
@Test | ||
fun 최근_검색_기록을_조회한다() { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1.copy(timestamp = 0)) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2.copy(timestamp = 1)) | ||
fun 최근_검색_기록을_조회한다() = | ||
runTest { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1.copy(timestamp = 0)) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2.copy(timestamp = 1)) | ||
|
||
// when | ||
val result = dao.getRecentHistoryProduct() | ||
// when | ||
val result = dao.getRecentHistoryProduct() | ||
|
||
// then | ||
assertThat(result?.productId).isEqualTo(DUMMY_HISTORY_PRODUCT_2.productId) | ||
} | ||
// then | ||
assertThat(result?.productId).isEqualTo(DUMMY_HISTORY_PRODUCT_2.productId) | ||
} | ||
|
||
@Test | ||
fun 총_검색_기록_개수를_조회한다() { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2) | ||
fun 총_검색_기록_개수를_조회한다() = | ||
runTest { | ||
// given | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_1) | ||
dao.insertHistory(DUMMY_HISTORY_PRODUCT_2) | ||
|
||
// when | ||
val count = dao.getHistoryCount() | ||
// when | ||
val count = dao.getHistoryCount() | ||
|
||
// then | ||
assertThat(count).isEqualTo(2) | ||
} | ||
// then | ||
assertThat(count).isEqualTo(2) | ||
} | ||
|
||
@Test | ||
fun 오래된_검색_기록을_원하는_개수만큼_삭제한다() { | ||
// given | ||
val base = System.currentTimeMillis() | ||
repeat(5) { index -> | ||
dao.insertHistory( | ||
DUMMY_HISTORY_PRODUCT_1.copy( | ||
productId = index.toLong(), | ||
timestamp = base + index, | ||
), | ||
) | ||
fun 오래된_검색_기록을_원하는_개수만큼_삭제한다() = | ||
runTest { | ||
// given | ||
val base = System.currentTimeMillis() | ||
repeat(5) { index -> | ||
dao.insertHistory( | ||
DUMMY_HISTORY_PRODUCT_1.copy( | ||
productId = index.toLong(), | ||
timestamp = base + index, | ||
), | ||
) | ||
} | ||
|
||
// when | ||
dao.deleteOldestHistories(2) | ||
|
||
// then | ||
val result = dao.getHistoryProducts() | ||
assertThat(result).hasSize(3) | ||
assertThat(result.map { it.productId }).doesNotContain(0) | ||
assertThat(result.map { it.productId }).doesNotContain(1) | ||
} | ||
|
||
// when | ||
dao.deleteOldestHistories(2) | ||
|
||
// then | ||
val result = dao.getHistoryProducts() | ||
assertThat(result).hasSize(3) | ||
assertThat(result.map { it.productId }).doesNotContain(0) | ||
assertThat(result.map { it.productId }).doesNotContain(1) | ||
} | ||
|
||
@After | ||
fun tearDown() { | ||
database.close() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package woowacourse.shopping.util | ||
|
||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.ExperimentalCoroutinesApi | ||
import kotlinx.coroutines.test.TestDispatcher | ||
import kotlinx.coroutines.test.UnconfinedTestDispatcher | ||
import kotlinx.coroutines.test.resetMain | ||
import kotlinx.coroutines.test.setMain | ||
import org.junit.jupiter.api.extension.AfterEachCallback | ||
import org.junit.jupiter.api.extension.BeforeEachCallback | ||
import org.junit.jupiter.api.extension.ExtensionContext | ||
|
||
@ExperimentalCoroutinesApi | ||
class CoroutinesTestExtension( | ||
private val dispatcher: TestDispatcher = UnconfinedTestDispatcher(), | ||
) : BeforeEachCallback, | ||
AfterEachCallback { | ||
override fun beforeEach(context: ExtensionContext?) { | ||
Dispatchers.setMain(dispatcher) | ||
} | ||
|
||
override fun afterEach(context: ExtensionContext?) { | ||
Dispatchers.resetMain() | ||
} | ||
} | ||
Comment on lines
+14
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CoroutineTestExtension의 활용 정말 좋습니다~ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,8 @@ | |
tools:targetApi="31"> | ||
<activity | ||
android:name=".ui.cart.CartActivity" | ||
android:exported="false" /> | ||
android:exported="false" | ||
android:parentActivityName=".ui.catalog.CatalogActivity" /> | ||
<activity | ||
android:name=".ui.catalog.CatalogActivity" | ||
android:exported="true"> | ||
|
@@ -30,7 +31,11 @@ | |
</activity> | ||
<activity | ||
android:name=".ui.productdetail.ProductDetailActivity" | ||
android:exported="false" /> | ||
android:exported="false" | ||
android:parentActivityName=".ui.catalog.CatalogActivity" /> | ||
<activity | ||
android:name=".ui.payment.PaymentActivity" | ||
android:exported="false" | ||
android:parentActivityName=".ui.catalog.CatalogActivity" /> | ||
Comment on lines
+36
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
</application> | ||
|
||
</manifest> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
package woowacourse.shopping | ||
|
||
import android.app.Application | ||
import woowacourse.shopping.di.DatabaseModule | ||
import woowacourse.shopping.di.PreferenceModule | ||
import woowacourse.shopping.di.DatabaseInjection | ||
import woowacourse.shopping.di.PreferenceInjection | ||
|
||
class ShoppingApp : Application() { | ||
override fun onCreate() { | ||
super.onCreate() | ||
DatabaseModule.init(this) | ||
PreferenceModule.init(this) | ||
DatabaseInjection.init(this) | ||
PreferenceInjection.init(this) | ||
Comment on lines
+10
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오호~ 저번 미션에서의 코멘트의 injection 이라는 네이밍이 마음에 드셨군요😊 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
앞으로는 |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
기획명세에 대한 정의와 README 작성 너무 좋네요~
추가적으로 한가지팁을 드려보자면, 단계별 나왔던 키워드를 살짝 남겨둔다면 추후에 해당 내용을 보았을 때 아~ 이때 이런 키워드가 나왔었지 이렇게 좀 더 기억에 남을 수도 있겠군요💪
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
한 번 열심히 리마인드 해보겠습니다~~~ 👍
b173040