IT한 것/Rust

[rust] async 기능 테스트하는 방법 (not tokio)

lovian 2023. 3. 7. 15:47

async 인 함수를 테스트 할 필요가 생겼다.

 

#[test]
async fn mytest () {
  println!("this is async fn");
}

이렇게 작성하면 다 될 것 같겠지만, 

 

error: async functions cannot be used for tests
  --> tests/basic_test.rs:66:1
   |
66 |   async fn mytest() {
   |   ^----
   |   |
   |  _`async` because of this
   | |
67 | |     println!("this is async fn");
68 | | }
   | |_^

그렇다 cargo test는 async 함수를 지원하지 않는다.

 

검색

여러모로 검색을 하다보면 tokio-test를 이용하면 된다는 답변이 많이 나오지만, 작지만 큰 문제가 있다.

나의 경우 wasm 빌드가 목적인데 tokio는 wasm을 지원안해서 그런지 Io에 대해서 빌드 오류가 발생한다.

wasm이 아닌 다른 타겟으로 바꾸어 테스트하면 문제는 없으나, 반쪽 짜리 이므로 다른 방법을 찾아보기 시작했다.

 

 

Future

여러 개발 언어/환경에서 비동기 처리를 위한 다양한 시스템을 제공하는데, rust의 경우 기본적으로 Future를 사용하는 것 같다.

나의 경우 wasm bindgen을 이용하는 중이라 Promise를 사용해야하는데, Promise는 std::future::Future로 변환이 가능했다.

그러므로 어떻게든 std::future::Future를 잘 핸들링 하면 문제는 해결될 수 있음을 짐작 할 수 있었다.

 

여기서 함정은 rust 초짜이므로 Future를 어떻게 쓰는지 모른다는 것.

 

슬프게도 깔끔하게 정리된 것을 찾을 수는 없었다.

 

Blocking

비동기 -> 동기 변환 하는 방법은 개념적으로는 간단하다.

비동기 작업이 완료될 때까지 다음 코드가 실행 안되게 잡고 있는 것.

 

현재 작업중이던 스레드 A를 재우고, 새 스레드 B에서 비동기 작업을 수행시키고 작업이 완료되면, 스레드 A를 깨우게되면 된다.

 

그러나 테스트 하는데 스레드 만들어 관리하는게 마음에 들지 않는다.

요즘은 누가 많이 만들어두니까 방향을 전환해서 탐색해봤다.

 

futures

futures 란 crate를 찾아냈다.

https://docs.rs/futures/latest/futures/

 

futures - Rust

Polls multiple futures and streams simultaneously, executing the branch for the future that finishes first. If multiple futures are ready, one will be pseudo-randomly selected at runtime. Futures directly passed to select! must be Unpin and implement Fused

docs.rs

 

나에게 필요한건 비동기 작업을 수행하는 역할을 하는 Executors를 제공한다는 것.

바로 반영해서 원하는 바를 얻었다.

 

#[test]
fn mytest() {
    let job = async {
        println!("this is async fn");
    };

    futures::executor::block_on(job);
}