Skip to content

Commit

Permalink
working on week 7 - test part end
Browse files Browse the repository at this point in the history
  • Loading branch information
4roring committed Oct 21, 2023
1 parent bf9f994 commit e84399e
Showing 1 changed file with 359 additions and 0 deletions.
359 changes: 359 additions & 0 deletions ppt/7_test_functional.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,362 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini
```

- 실행하면 테스트 수행 결과에 대한 로그가 나옴

---

```rust
#[test]
fn another() {
panic!("Make this test fail");
}
```

```
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s
```

- 실패하는 테스트 추가, FAILED 1이 된 것을 볼 수 있음

---

## assert! 매크로로 결과 검사

```rust
#[test]
fn test_compare() {
let a = "AAA";
let b = "AAA";
assert!(a == b);
}
```

- assert! 는 bool 값을 받아서 검사를 진행
- true 면 성공

---

## assert_eq!

```rust
#[test]
fn test_compare() {
let a = "AAA";
let b = "AAA";
assert_eq!(a, b);
}
```

- 두 인자가 같은지 검사

---

## assert_ne!

```rust
#[test]
fn test_compare() {
let a = "AAA";
let b = "AAA";
assert_eq!(a, b);
}
```

- 두 인자가 다른지 검사

---

## 커스텀 실패 메시지 추가

```rust
#[test]
fn test_compare() {
let a = "AAA";
let b = "BBB";
assert!(a == b, "{a} and {b} not equal" );
}
```

```
---- tests::test_compare2 stdout ----
thread 'tests::test_compare2' panicked at 'AAA and BBB not equal', src\main.rs:18:9
```

- assert! 두번째 인자로 format!을 넣을 수 있고 실패시 위와 같이 stdout으로 직접 작성한 메시지가 출력됨

---

## should_panic 속성

```rust
#[test]
#[should_panic]
fn test_panic() {
panic!("Should panic!");
}
```

- 테스트에서 panic! 발생을 체크

---

## Result<T, E>를 이용한 테스트

```rust
#[test]
fn it_works() -> Result<(), String> {
if 2 + 1 == 4 {
Ok(())
} else {
Err(String::from("two plus two does not equal four"))
}
}
```

```
---- tests::it_works stdout ----
Error: "two plus two does not equal four"
```

- 테스트 성공시에는 Ok() 를 반환
- 테스트 실패시에 Err(String)을 반환 후 테스트 실패 처리됨
- stdout에는 Err 안에 있는 String을 출력

---

## 테스트 실행 방법 제어

- -- 구분자를 쓰고 그 뒤에 테스트 바이너리에 전달할 인자를 작성
- **cargo test --help** : test 명령에 사용 가능한 옵션 표기
- **cargo test -- --help** : -- 구분자 이후 사용 가능한 옵션 표기

---

## 테스트를 병렬 혹은 순차적으로 실행하기

- 기본적으로 테스트는 병렬로 수행됨
- 동일한 파일에 대한 테스트를 예로 들면 병렬인 경우 실패의 가능성이 있음
- cargo test -- --test-threads=1
- 위 명령어로 스레드 하나에서 테스트를 진행하면 순차적으로 수행됨

---

- --show-output 옵션을 통하여 성공한 테스트의 출력도 볼 수 있다

```rust
#[test]
fn exploration() {
println!("Success Test");
assert_eq!(2 + 2, 4);
}
```

```
---- tests::exploration stdout ----
Success Test
```

---

## 명령어로 특정 테스트만 수행

- cargo test [테스트 이름] 으로 특정 테스트만 수행할 수 있다
- 첫 번째 인자의 테스트만 수행이되고 여러 테스트 수행은 불가능

---

## 필터를 통한 여러 테스트 수행

- cargo test [테스트 이름에 포함되는 문자열]
- 위 방법으로 테스트 이름에 문자열이 포함되는 여러 테스트 수행이 가능하다
- add의 경우 add_test, test_add, testadd, addtest 라는 이름의 테스트가 있는 경우 전부 수행

---

## ignore로 특정 테스트 무시

```rust
#[test]
#[ignore]
fn exploration() {
assert_eq!(2 + 2, 4);
}
```

- ignore 속성을 추가하여 테스트에서 제외할 수 있다
- cargo run -- --ignored 명령어를 입력하면 무시한 테스트만 수행 가능
- 모든 테스트를 수행하고 싶으면 --include ignored

---

## 테스트 조직화

- 러스트 커뮤니티에서는 크게 유닛 테스트, 통합 테스트로 나눔
- 유닛 테스트는 작고 집중적, 라이브러리, 함수 단위
- 통합 테스트는 라이브러리 외부에서 여러 모듈을 포함한 테스트

---

## 유닛 테스트

```rust
pub fn add(a: usize, b: usize) { a + b }

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_work() {
assert_eq!(add(2, 2), 4);
}
}
```

- 각 코드 단위를 나머지 코드와 분리하여 제대로 동작하지 않는 코드가 어느 부분인지 빠르게 파악
- 각 파일에 tests 모듈을 만들고 cfg(test)를 어노테이션 하는게 일반적인 관례
- 일반 코드와 같은 위치에 포함


---

```rust
fn internal_add(a: usize, b: usize) { a + b }

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn it_work() {
assert_eq!(internal_add(2, 2), 4);
}
}
```

- pub가 아닌 비공개 함수도 테스트 가능

---

## 통합 테스트

```
adder
├── Cargo.lock
├── Cargo.toml
├── src
│ └── lib.rs
└── tests
└── integration_test.rs
```

- src 폴더 옆에 tests 폴더를 생성
- cargo test는 프로젝트 하위의 모든 tests 폴더의 테스트 코드를 수행


---

integration_test.rs

```rust
use adder;
#[test]
fn it_adds_two() {
assert_eq!(4, adder::add_two(2));
}
```
- #[cfg(test)] 없이 동작

---

## 통합 테스트 내 서브 모듈

```
adder
└── tests
└── common.rs
```

```rust
pub fn setup() { ... }
```

```
Running tests\common.rs (target\debug\deps\common-417a720530eed599.exe)
```

- 위와 같이 common.rs를 추가하고 setup에서 테스트에 필요한 옵션들을 설정하고 싶은 상황
- 하지만 위 상태로 cargo test를 돌리면 common 모듈 테스트를 수행함
- 원하는 결과는 아니다

---

```
adder
└── tests
└── common
└── mod.rs
```

- 위와 같이 이전 명명 규칙을 통해서 모듈을 선언
- 테스트 대상이 되지 않음

---

## 바이너리 크레이트에서 테스트

- tests에서 main.rs의 모듈은 가져올 수 없음
- 그래서 바이너리 제공 프로젝트는 main은 간단하게 작성
- lib.rs에서 주로 작성

---

## 기능 테스트 vs 비기능 테스트

TODO: 간단하게 정리

---

# 함수형 언어의 특징: 반복자와 클로저

- 함수를 값처럼 넘기는 것
- 다른 함수 결과값을 함수로 반환하는 것
- 나중에 실행하기 위해 변수에 함수를 할당하는 것

---

## 클로저 (Closure)

- 변수나 다른 함수에 전달 할 수 있는 익명 함수
- 함수와 다른 점은 정의된 클래스에서 값을 캡처할 수 있음

---

## 캡처

```rust
impl MyFile {
fn create_file(&self, file_path: &str) { ... }

fn load_file(&self, file_path: &str) {
let greeting_file = File::open(file_path).unwrap_or_else(|| {
create_file(file_path);
});
}
}

```

---

```rust
fn add_one_v1(x: u32) -> u32 { x + 1 }
let add_one_v2 = |x: u32| -> u32 { x + 1 };
let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1;
```

- 함수와 비교하여 두번째는 모든 것이 명시된 클로저
- 세번째는 리턴 타입이 제거된 클로저
- 네번째는 표현식이 하나 뿐이라 중괄호도 없는 클로저


0 comments on commit e84399e

Please sign in to comment.