CodeBlanks Logo Icon CodeBlanks

Test infrastructure

Add integration tests with the tests/ folder.

Test setup

We secure the library's behaviour with tests. Tests live in the same file, in a module compiled only during cargo test:

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

    #[test]
    fn arama_yazara_gore_bulur() {
        let mut raf = Raf::new();
        raf.ekle(Kitap::new("Tutunamayanlar", "Oğuz Atay", 1972));
        assert_eq!(raf.ara("atay").len(), 1);
    }
}

The #[cfg(test)] module isn't included in a normal build; use super::.. brings the parent module's items into scope.

What should be tested?

Good tests check the contract the user relies on: the constructor storing values correctly, the search working regardless of case, a query with no matches returning an empty result. Each test should cover a single behaviour and have a descriptive name:

#[test]
fn arama_buyuk_kucuk_harf_duyarsiz() { .. }

#[test]
fn bulunamayan_sorgu_bos_doner() {
    let raf: Raf<Kitap> = Raf::new();
    assert!(raf.ara("xyz").is_empty());
}

Practice Tests and a check

Add #[cfg(test)] mod tests to the previous library code: write two #[test]s checking 2 results for ara("atay") with assert_eq! and an empty result for ara("xyz"). Since the exercise environment runs main, also do the same two checks with assert! in main and print tüm denetimler geçti.

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
mod kitaplik {
    pub struct Kitap {
        ad: String,
        yazar: String,
        yil: u16,
    }

    impl Kitap {
        pub fn new(ad: &str, yazar: &str, yil: u16) -> Self {
            Self {
                ad: ad.to_string(),
                yazar: yazar.to_string(),
                yil,
            }
        }
        pub fn ad(&self) -> &str {
            &self.ad
        }
        pub fn yil(&self) -> u16 {
            self.yil
        }
    }

    pub struct Raf<T> {
        ogeler: Vec<T>,
    }

    impl<T> Raf<T> {
        pub fn new() -> Self {
            Self { ogeler: Vec::new() }
        }
        pub fn ekle(&mut self, x: T) {
            self.ogeler.push(x);
        }
        pub fn len(&self) -> usize {
            self.ogeler.len()
        }
    }

    pub trait Aranabilir {
        fn eslesir(&self, sorgu: &str) -> bool;
    }

    impl Aranabilir for Kitap {
        fn eslesir(&self, sorgu: &str) -> bool {
            let s = sorgu.to_lowercase();
            self.ad.to_lowercase().contains(&s) || self.yazar.to_lowercase().contains(&s)
        }
    }

    impl<T: Aranabilir> Raf<T> {
        pub fn ara(&self, sorgu: &str) -> Vec<&T> {
            self.ogeler.iter().filter(|x| x.eslesir(sorgu)).collect()
        }
    }
}

use kitaplik::{Kitap, Raf};

fn ornek_raf() -> Raf<Kitap> {
    let mut raf = Raf::new();
    raf.ekle(Kitap::new("Tutunamayanlar", "Oğuz Atay", 1972));
    raf.ekle(Kitap::new("Tehlikeli Oyunlar", "Oğuz Atay", 1973));
    raf.ekle(Kitap::new("Kürk Mantolu Madonna", "Sabahattin Ali", 1943));
    raf
}

fn main() {
    let raf = ornek_raf();
    assert!(raf.ara("atay").len() == 2);
    assert!(raf.ara("xyz").is_empty());
    println!("tüm denetimler geçti");
}

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

    #[test]
    fn yazara_gore_bulur() {
        assert_eq!(ornek_raf().ara("atay").len(), 2);
    }

    #[test]
    fn bulunamayan_bos_doner() {
        assert!(ornek_raf().ara("xyz").is_empty());
    }
}

Expected output

tüm denetimler geçti

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does <code>cargo test</code> do when a test fails?

  • Stops immediately
  • Skips the test
  • Gives a compile error
  • Keeps running the other tests and reports the failures at the end Correct answer

Explanation: Each test runs on its own thread; one test's panic doesn't affect the others.

2 Compile only in tests

Question
#[____]
mod tests {
    #[test]
    fn ornek() {}
}
Answer
#[cfg(test)]
mod tests {
    #[test]
    fn ornek() {}
}

Explanation: #[cfg(test)] compiles the module only during cargo test.

3 Item and role

Term Meaning
#[cfg(test)] Conditional compilation
#[test] Test function
assert_eq!(a, b) Equality check
use super::* Brings the parent into scope

All lessons in Intermediate