210329 Mon
1. 첫 번째 학습 내용: Unit Test / TDD
TDD (Test-Driven Development) By 켄트 백
코드를 기능단위로 잘 분리를 해야만 테스트를 잘할 수 있음.
→ 작은 실패를 반복해서 원하는 골로 향한다.
리팩터란? 흐름 안에 있는 코드의 모양새를 바꾸는 것
더하기 연산 함수를 실행했을 때 1+1을 더해서 2가 나오는지?
테스트 하면서 확인하는게 테스트 코드!
하나의 메서드 안에 모든 기능 다 때려넣음
그러면 어떤 코드가 문제가 되는지 파악하기 힘듦!
스텍을 가지고 테스트 코드 작성한다.
Pop 메서드를 테스트하고 싶음
스텍은 애초에 비어있기 때문에
push를 한 다음에 pop을 하는 테스트 했음
만약에 push를 못하면 pop도 못함
push라는 메소드에 의존하고 있는 pop 테스트하는 거임
순수하게 pop만 테스트할 수 있는 코드를 작성해야 함
import Foundation
class Queue {
var arr: Array<String> = []
func enqueue(_ item: String) -> Array<String> {
arr.append(item)
return arr
}
func enqueMultipleItems(_ items: Array<String>) -> Array<String> {
for item in items {
arr.append(item)
}
return arr
}
func dequeue() -> Array<String> {
arr.removeFirst()
return arr
}
func dequeueMultipleItems(num: Int) -> Array<String> {
for _ in 1...num {
arr.removeFirst()
}
return arr
}
func removeAllItem() -> Array<String> {
arr = [] // 모든 아이템을 지워주려면 그냥 빈 배열로 만들어버리면 된다.
return arr
}
}
import XCTest
@testable import queue
class testQueue: XCTestCase {
var queue: Queue? // queue 프로퍼티는 Queue클래스를 상속받음?
override func setUpWithError() throws {
queue = Queue()
try super.setUpWithError()
}
override func tearDownWithError() throws {
try super.tearDownWithError()
}
func test_enqueue() {
XCTAssertEqual(queue.enqueue("yun"), ["yun"])
// Queue 클래스의 enqueue 메소드를 실행해서 yun을 입력했을떄 결과 값이 yun이 제대로 나오는지 테스트
}
}
테스트 관련 용어
- SUT: (System Under Test) : 주요 객체(primary object)
- Test Doubles: 오리지널 객체를 사용해서 테스트를 진행하기가 어려울 경우 이를 대신해서 테스트를 진행할 수 있도록 하는 객체를 의미한다.
- dummy
- 더미 객체는 말 그대로 멍청한 모조품, 단순한 껍데기에 해당한다.
- 단지 인스턴스화된 객체가 필요할 뿐 해당 객체의 기능까지는 필요하지 않은 경우에 사용한다.
- 따라서 해당 더미 객체의 메소드가 호출됐을 때의 정상 동작은 보장되지 않는다. 보통은 타입 기본값(0, null, false 등)으로 반환값을 만들어주는 선에서 마무리한다.
- stub:
- 더미 객체가 마치 실제로 동작하는 것처럼 보이게 만들어놓은 객체를 의미한다.
- 더미 객체로 만들어진 인스턴스의 메소드를 호출하면 타입 기본값으로 리턴되거나 아무 일도 일어나지 않는 데 비해 테스트 스텁은 객체의 특정 상태를 가정해서 만들었기 때문에 특정한 값을 리턴하거나 특정 메시지를 출력한다.
- Mock:
- 일반적으로는 조각하기 쉬운 재료를 이용해 추후 만들어질 제품의 외양을 흉내 낸 모조품을 의미한다.
- 소프트웨어 개발에 있어서 Mock은 모듈의 겉모양이 실제 모듈과 비슷하게 보이도록 만든 가짜 객체다.
- 우리가 구현을 하는 데 필요하지만 실제로 준비하기엔 여러 어려움이 따르는 대상을 필요한 부분만큼만 채워넣어서 만들어진 객체를 의미한다.
- fake:
- 여러 개의 인스턴스를 대표할 수 있는 경우이거나, 좀 더 복잡한 구현이 들어가 있는 객체를 지칭하는 단어이다.
- 복잡한 로직이나, 객체 내부에서 필요로 하는 다른 외부 객체들의 동작을 비교적 단순화하여 구현한 객체이다.
- 결과적으로는 테스트 케이스 작성을 진행하기 위해 필요한 다른 객체들과의 의존성을 제거하기 위해 사용된다.
- spy:
- 테스트에 사용되는 객체에 대해 특정 객체가 사용됐는지, 그리고 그 객체의 예상된 메소드가 정상적으로 호출됐는지 확인해야 하는 상황에서 호출 여부를 몰래 감시하여 기록했다가 요청이 들어오면 해당 기록을 전달한다.
- 특정 메소드의 정상호출 여부 확인을 목적으로 구현되며, 더미부터 시작해서 페이크 객체에 이르기까지 테스트 더블로 구현된 객체 전 범위에 걸쳐 해당 기능을 추가할 수 있다. 테스트 스파이 객체는 다른 동작을 하면서 스파이 기능까지 하는 경우가 많다.
출처:
"TDD 실천법과 도구" 책 전체를 PDF 공개합니다. https://repo.yona.io/doortts/blog/issue/1
TDD (Test Driven Development) 란? https://velog.io/@sbyeol3/TDD-Test-Driven-Development-란
2. 두 번째 학습 내용: Stack 자료구조 구현
import UIKit
public struct Stack<T> {
private var elements = [T]()
public init() {}
public mutating func push(_ element: T) {
self.elements.append(element)
}
public mutating func pop() -> T? {
return self.elements.popLast()
}
public func peek() -> T? {
return self.elements.last
}
public func isEmpty() -> Bool {
return self.elements.isEmpty
}
public var count: Int {
return self.elements.count
}
}
var myStack = Stack<Int>()
myStack.isEmpty()
myStack.push(1)
print(myStack)
myStack.isEmpty()
myStack.push(2)
print(myStack)
myStack.count
myStack.peek()
myStack.pop()
print(myStack)
출처: https://gimjinging.tistory.com/83
Author And Source
이 문제에 관하여(210329 Mon), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sunnywhynot/210329-Mon저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)