#0. 테이블 드리븐 테스트에서 터미널에 출력하는 함수 테스트
os.stdout에 표준출력을 우리의 write pipe로 바꿔주고, 바꿔준 pipe로 문자열을 읽어들여서 비교해서 테스트.
#1. 실습
maim.go와 main_test.go로 테스트 실습.
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
// print a welcome message
intro()
// create a channel to indicate when the user wants to quit
doneChan := make(chan bool)
// start a goroutine to read user input and run program
go readUserInput(doneChan)
// block until the doneChan gets a value
<-doneChan
// close the channel
close(doneChan)
// say goodbye
fmt.Println("Goodbye.")
}
func readUserInput(doneChan chan bool) {
scanner := bufio.NewScanner(os.Stdin)
for {
res, done := checkNumbers(scanner)
if done {
doneChan <- true
return
}
fmt.Println(res)
prompt()
}
}
func checkNumbers(scanner *bufio.Scanner) (string, bool) {
// read user input
scanner.Scan()
//check to see if the user wants to quit
if strings.EqualFold(scanner.Text(), "q") {
return "", true
}
// try to convert what the user typed into an int
numToCheck, err := strconv.Atoi(scanner.Text())
if err != nil {
return "Please enter a whole number", false
}
_, msg := isPrime(numToCheck)
return msg, false
}
func intro() {
fmt.Println("Is it Prime?")
fmt.Println("------------")
fmt.Println("Enter a whole number, and we'll tell you if it is a prime number or not. Enter q to quit.")
prompt()
}
func prompt() {
fmt.Print("-> ")
}
func isPrime(n int) (bool, string) {
// 0과 1 처리(0과 1은 소수가 아님)
if n == 0 || n == 1 {
return false, fmt.Sprintf("%d is not prime, by definition!", n)
}
// 0보다 작은 수의 경우
if n < 0 {
return false, "Negative numbers are not prime, by definition!"
}
// 소수인지 아닌지 체크
for i := 2; i <= n/2; i++ {
if n%i == 0 {
// 소수가 아닌 경우
return false, fmt.Sprintf("%d is not a prime number because it is divisible by %d!", n, i)
}
}
//소수인 경우
return true, fmt.Sprintf("%d is a prime number!", n)
}
1. main.go 파일
소수인지 체크하는 프로그램으로써. 소수인 경우, 소수가 아닌 경우, 0과1인 경우, 0보다작은 경우(-1)를 체크한다.
그리고 사용자에게 입력을 받고 문자열을 출력하는 함수(intro(), prompt(), checkNumbers(), readUserInput())들을 추가했다.
package main
import (
"io"
"os"
"testing"
)
func Test_isPrime(t *testing.T) {
primeTests := []struct {
name string
testNum int
expected bool
msg string
}{
// 1. testNum의 이름, 2. 테스트할 값, 3. 예상되는 값(bool), 4. 예상되는 msg(string)
{"prime", 7, true, "7 is a prime number!"},
{"not prime", 8, false, "8 is not a prime number because it is divisible by 2!"},
{"zero", 0, false, "0 is not prime, by definition!"},
{"one", 1, false, "1 is not prime, by definition!"},
{"negative number", -11, false, "Negative numbers are not prime, by definition!"},
}
for _, e := range primeTests {
//테스트 값을 넣어주고 반환값을 얻음
result, msg := isPrime(e.testNum)
// 예상되는 값(bool)이 true 이지만 false를 얻은 경우 테스트 실패
if e.expected && !result {
t.Errorf("%s: expected true but got false", e.name)
}
// 예상되는 값(bool)이 false 이지만 true를 얻은 경우 테스트 실패
if !e.expected && result {
t.Errorf("%s: expected false but got true", e.name)
}
// 반환된 값(string)과 예상되는 값(string) 메세지가 다른 경우 테스트 실패
if e.msg != msg {
t.Errorf("%s: expected %s but got %s", e.name, e.msg, msg)
}
}
}
func Test_prompt(t *testing.T) {
// save a copy of os.Stdout
oldOut := os.Stdout
// create a read and write pipe
r, w, _ := os.Pipe()
//set os.Stdout to our write pipe
os.Stdout = w
prompt()
// close our writer
_ = w.Close()
// reset os.Stdout to what it was before
os.Stdout = oldOut
// read the output of our prompt() func from our read pipe
out, _ := io.ReadAll(r)
// perform our test
if string(out) != "-> " {
t.Errorf("incorrect prompt: expected -> but got %s", string(out))
}
}
2. main_test.go 파일 (func Test_prompt)
1. oldOut 변수에 표준출력을 저장시켜 놓음.
2. os.pipe() 함수를 통해서 읽거나 쓸수 있는 파일 쌍을 반환
3. os.Stdout = w, 표준출력을 설정한 os.Stdout에 os.Pipe로 반환한 w(파일에 쓸수 있는)를 적용시킴
4. prompt()를 실행 시켜서 터미널에 출력하던 문자열을 w로 출력함.
5. w.Close()로 w를 닫아줌.
6. os.Stdout = oldOut을 통해서 다시 표준출력으로 복구시킴.
7. out, _ := io.ReadAll(r), 4번을 통해서 실행 시킨 문자열을 out으로 모두 읽어옴
8. if string(out) != "-> ", prompt 함수에서 출력하는 문자열이 맞는지 확인.
#2. 결과
1. go test -v, go test -cover 명령어로 테스트 범위와 통과 확인.
2. go test . -coverprofile=coverage.out 명령어로 coverage.out 파일을 만들어줌
3. go tool cover -html=coverage.out(윈도우에서는 .out없이) 명령어로 html 파일로 확인. (초록색 부분이 cover(테스트 코드 작성 완료))
출처
https://www.udemy.com/course/introduction-to-testing-in-go-golang/
'프로그래밍 > Go(golang) 테스트 공부' 카테고리의 다른 글
#4. golang 채널과 고루틴을 사용하는 함수에 대한 테스트 코드(with 유데미) (0) | 2023.11.12 |
---|---|
#3. golang 사용자 입력에 대한 테스트 코드(with 유데미) (0) | 2023.11.11 |
#1. golang 테이블 드리븐 테스트(with 유데미) (0) | 2023.10.30 |
#0. golang 테스트 코드 공부(with 유데미) (0) | 2023.10.28 |