-
Notifications
You must be signed in to change notification settings - Fork 47
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
[둘리] 1, 2단계 쇼핑 장바구니 제출합니다. #20
Merged
Merged
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit
Hold shift + click to select a range
d7cfbc7
docs: 기능 목록 작성
hyemdooly 2584164
feat: Domain 모듈 생성
hyemdooly 5ae38d7
feat: 상훔 목록을 관리하는 Repository Interface 생성
hyunji1203 d9c9fb4
feat: 장바구니를 관리하는 CartRepository Interface 생성
hyemdooly 2676ad4
feat: 최근 본 상품 목록을 관리하는 Repository Interface 생성
hyunji1203 e65d164
feat: 상품 정보를 담는 Product, 가격을 담는 Price 생성
hyemdooly 42ca12e
feat: 상품의 정보를 리턴하는 ProductMockRepository 구현
hyunji1203 25d3651
feat: ProductListActivity 이미지 제외한 화면 구성 완료
hyemdooly ccb8fc1
feat: 메인 색깔 변경
hyemdooly 52e3bc5
feat: 액션 바에 장바구니 바로가기 메뉴 추가
hyunji1203 143e31c
feat: 장바구니 화면의 액션바 안의 백버튼을 누르면 뒤로 이동하는 기능 추가
hyunji1203 633ef00
feat: 상품 이미지 Glide 적용
hyemdooly 1f24cee
refactor: 패키지 이동
hyemdooly 8dc0249
refactor: ProductListActivity MVP 패턴 적용
hyunji1203 7cca774
refactor: 장바구니 아이템 구현
hyemdooly f45ba61
feat: 장바구니 리스트 뷰 구현
hyunji1203 b58de23
feat: 상품 상세 뷰 구현
hyemdooly 964767b
feat: 장바구니 DataBase 생성 로직 구현
hyunji1203 c2fc7af
feat: CartDbRepository 구현
hyemdooly 78d597e
feat: ProductList OnClick 추가, DB 적용
hyemdooly 605c01c
feat: 상품 상세 페이지 액션 바에 뒤로가기 버튼 추가
hyunji1203 0aaecc9
refactor: MVP 패턴으로 변경
hyunji1203 a2eb1fe
feat: 최근 본 상품 리스트 추가
hyemdooly 8da62a1
feat: 최근 본 상품 datebase 기능 추가
hyunji1203 9270d70
feat: CartProduct DB 적용, 삭제 기능 추가
hyemdooly 3136470
refactor: find 리턴값 수정
hyemdooly 3206da5
refactor: notifyItemRemoved 적용
hyemdooly b83401a
feat: 페이지네이션 구현 중
hyunji1203 f858baa
feat: 더보기 구현중
hyemdooly ea478c3
feat: 더보기 구현 완료
hyemdooly a143b22
feat: 카트 페이지네이션 구현 중
hyunji1203 3bf6ad5
test: ProductListPresenterTest 작성
hyemdooly 315a8ce
refactor: ProductDetailPresenter cartRepository 추상화 적용
hyemdooly 9599973
test: ProductDetailPresenter 테스트 추가
hyunji1203 8fd10a2
refactor: Pagination 적용중
hyemdooly 08ccb68
refactor: Pagination 적용중
hyemdooly 1330e9d
feat: Pagination Button onClick 수정
hyemdooly 65cee56
fix: 페이지가 넘어가지 않는 오류 수정
hyemdooly ef8e6c9
refactor: onCreate 코드 함수 분리
hyemdooly bb1c417
refactor: 너무 긴 코드 개행
hyemdooly bf285df
refactor: 상수 선언
hyemdooly 377f7b3
refactor: constraintLayout 자식 뷰 match_parent -> 0dp로 수정
hyemdooly 11cfe23
refactor: xml formatting
hyemdooly 4fbc614
refactor: asSequence 사용하여 map 호출 시간 단축
hyemdooly 68d3fdb
refactor: Next, Prev Pagination 분리
hyemdooly 5e57cd5
refactor: CartPageStatus 생성, CartAdapter 리팩터링
hyemdooly 023a703
refactor: LayoutManager xml로 이동
hyemdooly d3a1f22
refactor: 상수 선언
hyemdooly 41b0e02
refactor: CartAdapter에서 CartViewItem 사용하여 Items를 하나로 묶음
hyemdooly 5eb3cfc
refactor: ProductListActivity 리사이클러뷰 리팩터링
hyemdooly 6e8f667
test: package 이동, ProductListPresenterTest 수정, CartPresenterTest 작성
hyemdooly 0b23bbd
refactor: 테스트 코드에서 whildcard import 수정
hyemdooly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 0 additions & 3 deletions
3
app/src/main/java/woowacourse/shopping/view/cart/CartContract.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 3 additions & 3 deletions
6
...wacourse/shopping/model/CartPagination.kt → ...urse/shopping/view/cart/CartPagination.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
app/src/main/java/woowacourse/shopping/view/productlist/ProductListContract.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...e/shopping/model/ProductListPagination.kt → ...view/productlist/ProductListPagination.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 0 additions & 2 deletions
2
app/src/main/java/woowacourse/shopping/view/productlist/ProductListViewItem.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
app/src/test/java/woowacourse/shopping/CartPresenterTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
package woowacourse.shopping | ||
|
||
import android.util.Log | ||
import io.mockk.* | ||
import org.junit.Assert.assertEquals | ||
import org.junit.Before | ||
import org.junit.Test | ||
import woowacourse.shopping.domain.* | ||
import woowacourse.shopping.model.CartPageStatus | ||
import woowacourse.shopping.model.CartProductModel | ||
import woowacourse.shopping.model.ProductModel | ||
import woowacourse.shopping.model.toUiModel | ||
import woowacourse.shopping.view.cart.CartContract | ||
import woowacourse.shopping.view.cart.CartPresenter | ||
import woowacourse.shopping.view.cart.CartViewItem | ||
import woowacourse.shopping.view.productlist.ProductListContract | ||
import woowacourse.shopping.view.productlist.ProductListPresenter | ||
import woowacourse.shopping.view.productlist.ProductListViewItem | ||
|
||
class CartPresenterTest { | ||
private lateinit var presenter: CartContract.Presenter | ||
private lateinit var view: CartContract.View | ||
|
||
@Before | ||
fun setUp() { | ||
view = mockk(relaxed = true) | ||
val productRepository = object : ProductRepository { | ||
private val mProducts = products | ||
override fun findAll(): List<Product> { | ||
return mProducts | ||
} | ||
|
||
override fun find(id: Int): Product { | ||
return mProducts[id] | ||
} | ||
|
||
override fun findRange(mark: Int, rangeSize: Int): List<Product> { | ||
return mProducts.subList(mark, mark + rangeSize) | ||
} | ||
|
||
override fun isExistByMark(mark: Int): Boolean { | ||
return mProducts.find { it.id == mark } != null | ||
} | ||
} | ||
|
||
val cartRepository = object : CartRepository { | ||
private val cartProducts = mutableListOf<CartProduct>() | ||
init { | ||
cartProducts.add(CartProduct(0, 1)) | ||
cartProducts.add(CartProduct(1, 1)) | ||
cartProducts.add(CartProduct(2, 1)) | ||
cartProducts.add(CartProduct(3, 1)) | ||
cartProducts.add(CartProduct(4, 1)) | ||
cartProducts.add(CartProduct(5, 1)) | ||
cartProducts.add(CartProduct(6, 1)) | ||
cartProducts.add(CartProduct(7, 1)) | ||
|
||
} | ||
|
||
override fun findAll(): List<CartProduct> { | ||
return cartProducts | ||
} | ||
|
||
override fun add(id: Int, count: Int) { | ||
cartProducts.add(CartProduct(id, count)) | ||
} | ||
|
||
override fun remove(id: Int) { | ||
cartProducts.remove(cartProducts.find { it.id == id }) | ||
} | ||
|
||
override fun findRange(mark: Int, rangeSize: Int): List<CartProduct> { | ||
return cartProducts.subList(mark, mark + rangeSize) | ||
} | ||
|
||
override fun isExistByMark(mark: Int): Boolean { | ||
return cartProducts.getOrNull(mark) != null | ||
} | ||
|
||
} | ||
|
||
presenter = CartPresenter(view, cartRepository, productRepository) | ||
presenter.fetchProducts() | ||
} | ||
|
||
@Test | ||
fun 장바구니의_상품을_띄울_수_있다() { | ||
val items = slot<List<CartViewItem>>() | ||
every { view.showProducts(capture(items)) } just runs | ||
presenter.fetchProducts() | ||
val itemsExpected = listOf<CartViewItem>( | ||
CartViewItem.CartProductItem(CartProduct(0, 1).toUiModel(products[0])), | ||
CartViewItem.CartProductItem(CartProduct(1, 1).toUiModel(products[1])), | ||
CartViewItem.CartProductItem(CartProduct(2, 1).toUiModel(products[2])), | ||
CartViewItem.CartProductItem(CartProduct(3, 1).toUiModel(products[3])), | ||
CartViewItem.CartProductItem(CartProduct(4, 1).toUiModel(products[4])), | ||
) + CartViewItem.PaginationItem(CartPageStatus( | ||
isPrevEnabled = false, | ||
isNextEnabled = true, | ||
count = 1 | ||
)) | ||
assertEquals(itemsExpected, items.captured) | ||
} | ||
|
||
@Test | ||
fun 장바구니_상품을_삭제할_수_있다() { | ||
val actualId = slot<Int>() | ||
every { view.notifyRemoveItem(capture(actualId)) } just runs | ||
presenter.removeProduct(0) | ||
assertEquals(0, actualId.captured) | ||
} | ||
|
||
private val products = listOf( | ||
Product(0, "락토핏", "", Price(10000)), | ||
Product(1, "락토핏", "", Price(10000)), | ||
Product(2, "락토핏", "", Price(10000)), | ||
Product(3, "락토핏", "", Price(10000)), | ||
Product(4, "락토핏", "", Price(10000)), | ||
Product(5, "락토핏", "", Price(10000)), | ||
Product(6, "락토핏", "", Price(10000)), | ||
Product(7, "락토핏", "", Price(10000)), | ||
Product(8, "락토핏", "", Price(10000)), | ||
Product(9, "락토핏", "", Price(10000)), | ||
Product(10, "락토핏", "", Price(10000)), | ||
Product(11, "락토핏", "", Price(10000)), | ||
Product(12, "락토핏", "", Price(10000)), | ||
Product(13, "락토핏", "", Price(10000)), | ||
Product(14, "락토핏", "", Price(10000)), | ||
Product(15, "락토핏", "", Price(10000)), | ||
Product(16, "락토핏", "", Price(10000)), | ||
Product(17, "락토핏", "", Price(10000)), | ||
Product(18, "락토핏", "", Price(10000)), | ||
Product(19, "락토핏", "", Price(10000)), | ||
Product(20, "락토핏", "", Price(10000)), | ||
Product(21, "락토핏", "", Price(10000)), | ||
) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
slot을 사용하여 실제 객체를 감싸도록 구현해주셨네요.
더미객체를 사용하지 않고 slot을 사용하게 되면 어떤 이점이 있을까요?
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.
더미객체를 사용하는 것은
verify { view.showProducts(dummyObject) }
검증 코드를 사용하는 것을 말씀하시는 걸까요?!verify만 사용하여 검증하는 것은 정말 그 함수가 실행됐는지와, 인자가 다르다면 어떤 인자가 다른지까지는 알 수 있습니다.
다만 slot을 사용하면 실제 들어가는 인자를 가져올 수 있기 때문에, 좀 더 구체적으로 테스트를 진행할 수 있다고 생각합니다.
위 코드는 지금 수정한 CartPresenterTest의 일부인데요! items의 마지막은 data class가 아닌 '더보기' 객체라, 단순히 비교가 불가능했습니다.
따라서 저는 마지막 요소만 같은 클래스인지 확인하도록 코드를 작성했습니다.
itemExpected가 정말로 실행됐는지 확인하기위해 verify를 사용했다면 '더보기' 객체가 달라 test가 fail되었을 것입니다.
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.
상황에 맞게 slot에 대해서 잘 알고 쓰셨네요. 👍
그러나, cartItems가 멤버 변수이다보니 fetchProducts 함수를 테스트하기가 어렵기에 slot을 사용하여 테스트 코드를 작성한 것으로 보이네요.
혹시 이 테스트 코드는 반드시 성공하기 위해 작성된 코드라고 느껴지지 않으신가요?
내가 원하는 데이터를 가지고 함수를 호출하고, 그 결괏값이 내가 원하는 데이터가 맞는지를 검증하는 방향으로 개선해보면 어떨까요?
참고로 slot과 같은 것을 "스파이" 기법이라고 합니다.
"스파이"는 실제로 사용하는 객체를 시뮬레이션하는 것이 아니라, 감시하고 있는 근본 객체와의 모든 상호작용을 기록합니다.
여기에서는
view.showProducts
함수의 파라미터로 사용한 객체의 모든 상호작용을 기록합니다.그렇기에 "스파이"는 성공을 위한 테스트 코드를 작성하기 쉽습니다.
이러한 이유로 가급적이면 "스파이"는 현업에서는 잘 사용하지 않기도 합니다. 😅