[{"data":1,"prerenderedAt":1726},["ShallowReactive",2],{"page-\u002Frust\u002F21-testing":3},{"id":4,"title":5,"body":6,"description":1719,"extension":1720,"meta":1721,"navigation":133,"path":1722,"seo":1723,"stem":1724,"__hash__":1725},"content\u002Frust\u002F21-testing.md","21 — Testing in Rust",{"type":7,"value":8,"toc":1694},"minimark",[9,13,22,27,62,66,388,425,429,539,543,551,619,633,638,644,651,655,732,749,773,779,783,786,792,795,813,817,886,908,914,985,990,1029,1036,1040,1105,1115,1119,1240,1246,1250,1260,1352,1356,1361,1412,1416,1436,1440,1538,1542,1566,1573,1577,1583,1627,1640,1649,1653,1687,1690],[10,11,5],"h1",{"id":12},"_21-testing-in-rust",[14,15,16,17,21],"p",{},"Rust's testing is built into the language and ",[18,19,20],"code",{},"cargo",". There are three layers: unit tests, integration tests, and documentation tests.",[23,24,26],"h2",{"id":25},"test-categories","Test Categories",[28,29,30,42,52],"ol",{},[31,32,33,37,38,41],"li",{},[34,35,36],"strong",{},"Unit tests",": live inside the source, in ",[18,39,40],{},"#[cfg(test)] mod tests",". Test private items.",[31,43,44,47,48,51],{},[34,45,46],{},"Integration tests",": live in ",[18,49,50],{},"tests\u002F"," as separate crates. Test public API.",[31,53,54,57,58,61],{},[34,55,56],{},"Doc tests",": code in ",[18,59,60],{},"\u002F\u002F\u002F"," doc comments, run as examples.",[23,63,65],{"id":64},"writing-a-unit-test","Writing a Unit Test",[67,68,70],"code-wrapper",{"language":69},"rust",[71,72,76],"pre",{"className":73,"code":74,"language":69,"meta":75,"style":75},"language-rust shiki shiki-themes github-light github-dark","pub fn add(a: i32, b: i32) -> i32 { a + b }\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn adds_two() {\n        assert_eq!(add(2, 2), 4);\n    }\n\n    #[test]\n    #[should_panic(expected = \"negative\")]\n    fn rejects_negative() {\n        panic!(\"negative not allowed\");\n    }\n\n    #[test]\n    fn returns_result() -> Result\u003C(), String> {\n        if add(2, 2) == 4 { Ok(()) } else { Err(String::from(\"bad\")) }\n    }\n}\n","",[18,77,78,128,135,141,153,169,174,180,192,223,229,234,239,255,265,278,283,288,293,318,377,382],{"__ignoreMap":75},[79,80,83,87,90,94,98,101,104,107,109,111,114,117,119,122,125],"span",{"class":81,"line":82},"line",1,[79,84,86],{"class":85},"svdQ7","pub",[79,88,89],{"class":85}," fn",[79,91,93],{"class":92},"sIsaT"," add",[79,95,97],{"class":96},"ssxIu","(a",[79,99,100],{"class":85},":",[79,102,103],{"class":92}," i32",[79,105,106],{"class":96},", b",[79,108,100],{"class":85},[79,110,103],{"class":92},[79,112,113],{"class":96},") ",[79,115,116],{"class":85},"->",[79,118,103],{"class":92},[79,120,121],{"class":96}," { a ",[79,123,124],{"class":85},"+",[79,126,127],{"class":96}," b }\n",[79,129,131],{"class":81,"line":130},2,[79,132,134],{"emptyLinePlaceholder":133},true,"\n",[79,136,138],{"class":81,"line":137},3,[79,139,140],{"class":96},"#[cfg(test)]\n",[79,142,144,147,150],{"class":81,"line":143},4,[79,145,146],{"class":85},"mod",[79,148,149],{"class":92}," tests",[79,151,152],{"class":96}," {\n",[79,154,156,159,163,166],{"class":81,"line":155},5,[79,157,158],{"class":85},"    use",[79,160,162],{"class":161},"snvgF"," super",[79,164,165],{"class":85},"::*",[79,167,168],{"class":96},";\n",[79,170,172],{"class":81,"line":171},6,[79,173,134],{"emptyLinePlaceholder":133},[79,175,177],{"class":81,"line":176},7,[79,178,179],{"class":96},"    #[test]\n",[79,181,183,186,189],{"class":81,"line":182},8,[79,184,185],{"class":85},"    fn",[79,187,188],{"class":92}," adds_two",[79,190,191],{"class":96},"() {\n",[79,193,195,198,201,204,206,209,212,214,217,220],{"class":81,"line":194},9,[79,196,197],{"class":92},"        assert_eq!",[79,199,200],{"class":96},"(",[79,202,203],{"class":92},"add",[79,205,200],{"class":96},[79,207,208],{"class":161},"2",[79,210,211],{"class":96},", ",[79,213,208],{"class":161},[79,215,216],{"class":96},"), ",[79,218,219],{"class":161},"4",[79,221,222],{"class":96},");\n",[79,224,226],{"class":81,"line":225},10,[79,227,228],{"class":96},"    }\n",[79,230,232],{"class":81,"line":231},11,[79,233,134],{"emptyLinePlaceholder":133},[79,235,237],{"class":81,"line":236},12,[79,238,179],{"class":96},[79,240,242,245,248,252],{"class":81,"line":241},13,[79,243,244],{"class":96},"    #[should_panic(expected ",[79,246,247],{"class":85},"=",[79,249,251],{"class":250},"sJ6F3"," \"negative\"",[79,253,254],{"class":96},")]\n",[79,256,258,260,263],{"class":81,"line":257},14,[79,259,185],{"class":85},[79,261,262],{"class":92}," rejects_negative",[79,264,191],{"class":96},[79,266,268,271,273,276],{"class":81,"line":267},15,[79,269,270],{"class":92},"        panic!",[79,272,200],{"class":96},[79,274,275],{"class":250},"\"negative not allowed\"",[79,277,222],{"class":96},[79,279,281],{"class":81,"line":280},16,[79,282,228],{"class":96},[79,284,286],{"class":81,"line":285},17,[79,287,134],{"emptyLinePlaceholder":133},[79,289,291],{"class":81,"line":290},18,[79,292,179],{"class":96},[79,294,296,298,301,304,306,309,312,315],{"class":81,"line":295},19,[79,297,185],{"class":85},[79,299,300],{"class":92}," returns_result",[79,302,303],{"class":96},"() ",[79,305,116],{"class":85},[79,307,308],{"class":92}," Result",[79,310,311],{"class":96},"\u003C(), ",[79,313,314],{"class":92},"String",[79,316,317],{"class":96},"> {\n",[79,319,321,324,326,328,330,332,334,336,339,342,345,348,351,354,356,359,361,363,366,369,371,374],{"class":81,"line":320},20,[79,322,323],{"class":85},"        if",[79,325,93],{"class":92},[79,327,200],{"class":96},[79,329,208],{"class":161},[79,331,211],{"class":96},[79,333,208],{"class":161},[79,335,113],{"class":96},[79,337,338],{"class":85},"==",[79,340,341],{"class":161}," 4",[79,343,344],{"class":96}," { ",[79,346,347],{"class":92},"Ok",[79,349,350],{"class":96},"(()) } ",[79,352,353],{"class":85},"else",[79,355,344],{"class":96},[79,357,358],{"class":92},"Err",[79,360,200],{"class":96},[79,362,314],{"class":92},[79,364,365],{"class":85},"::",[79,367,368],{"class":92},"from",[79,370,200],{"class":96},[79,372,373],{"class":250},"\"bad\"",[79,375,376],{"class":96},")) }\n",[79,378,380],{"class":81,"line":379},21,[79,381,228],{"class":96},[79,383,385],{"class":81,"line":384},22,[79,386,387],{"class":96},"}\n",[389,390,391,397,409,415],"ul",{},[31,392,393,396],{},[18,394,395],{},"#[test]"," marks a test function.",[31,398,399,211,402,211,405,408],{},[18,400,401],{},"assert!",[18,403,404],{},"assert_eq!",[18,406,407],{},"assert_ne!",".",[31,410,411,414],{},[18,412,413],{},"#[should_panic(expected = \"...\")]"," for panic tests.",[31,416,417,418,421,422,424],{},"Returning ",[18,419,420],{},"Result\u003C(), E: Debug>"," is allowed — ",[18,423,358],{}," fails the test.",[23,426,428],{"id":427},"running-tests","Running Tests",[67,430,432],{"language":431},"bash",[71,433,436],{"className":434,"code":435,"language":431,"meta":75,"style":75},"language-bash shiki shiki-themes github-light github-dark","cargo test                 # all tests\ncargo test add             # filter by name substring\ncargo test --lib           # only lib unit tests\ncargo test --test integration   # only specific integration test\ncargo test -- --nocapture  # show println! output\ncargo test -- --test-threads=4\ncargo test --release       # tests in release mode\ncargo test -- --ignored    # run #[ignore] tests\n",[18,437,438,449,460,472,487,502,513,525],{"__ignoreMap":75},[79,439,440,442,445],{"class":81,"line":82},[79,441,20],{"class":92},[79,443,444],{"class":250}," test",[79,446,448],{"class":447},"sdCPZ","                 # all tests\n",[79,450,451,453,455,457],{"class":81,"line":130},[79,452,20],{"class":92},[79,454,444],{"class":250},[79,456,93],{"class":250},[79,458,459],{"class":447},"             # filter by name substring\n",[79,461,462,464,466,469],{"class":81,"line":137},[79,463,20],{"class":92},[79,465,444],{"class":250},[79,467,468],{"class":161}," --lib",[79,470,471],{"class":447},"           # only lib unit tests\n",[79,473,474,476,478,481,484],{"class":81,"line":143},[79,475,20],{"class":92},[79,477,444],{"class":250},[79,479,480],{"class":161}," --test",[79,482,483],{"class":250}," integration",[79,485,486],{"class":447},"   # only specific integration test\n",[79,488,489,491,493,496,499],{"class":81,"line":155},[79,490,20],{"class":92},[79,492,444],{"class":250},[79,494,495],{"class":161}," --",[79,497,498],{"class":161}," --nocapture",[79,500,501],{"class":447},"  # show println! output\n",[79,503,504,506,508,510],{"class":81,"line":171},[79,505,20],{"class":92},[79,507,444],{"class":250},[79,509,495],{"class":161},[79,511,512],{"class":161}," --test-threads=4\n",[79,514,515,517,519,522],{"class":81,"line":176},[79,516,20],{"class":92},[79,518,444],{"class":250},[79,520,521],{"class":161}," --release",[79,523,524],{"class":447},"       # tests in release mode\n",[79,526,527,529,531,533,536],{"class":81,"line":182},[79,528,20],{"class":92},[79,530,444],{"class":250},[79,532,495],{"class":161},[79,534,535],{"class":161}," --ignored",[79,537,538],{"class":447},"    # run #[ignore] tests\n",[23,540,542],{"id":541},"integration-tests","Integration Tests",[71,544,549],{"className":545,"code":547,"language":548},[546],"language-text","tests\u002F\n└── integration_test.rs\n","text",[18,550,547],{"__ignoreMap":75},[67,552,553],{"language":69},[71,554,556],{"className":73,"code":555,"language":69,"meta":75,"style":75},"use my_crate::add;\n\n#[test]\nfn integration_add() {\n    assert_eq!(add(2, 3), 5);\n}\n",[18,557,558,571,575,580,590,615],{"__ignoreMap":75},[79,559,560,563,566,568],{"class":81,"line":82},[79,561,562],{"class":85},"use",[79,564,565],{"class":92}," my_crate",[79,567,365],{"class":85},[79,569,570],{"class":96},"add;\n",[79,572,573],{"class":81,"line":130},[79,574,134],{"emptyLinePlaceholder":133},[79,576,577],{"class":81,"line":137},[79,578,579],{"class":96},"#[test]\n",[79,581,582,585,588],{"class":81,"line":143},[79,583,584],{"class":85},"fn",[79,586,587],{"class":92}," integration_add",[79,589,191],{"class":96},[79,591,592,595,597,599,601,603,605,608,610,613],{"class":81,"line":155},[79,593,594],{"class":92},"    assert_eq!",[79,596,200],{"class":96},[79,598,203],{"class":92},[79,600,200],{"class":96},[79,602,208],{"class":161},[79,604,211],{"class":96},[79,606,607],{"class":161},"3",[79,609,216],{"class":96},[79,611,612],{"class":161},"5",[79,614,222],{"class":96},[79,616,617],{"class":81,"line":171},[79,618,387],{"class":96},[389,620,621,627],{},[31,622,623,624,626],{},"Separate crate; can only use ",[18,625,86],{}," API.",[31,628,629,630,632],{},"Multiple files in ",[18,631,50],{}," become separate test binaries.",[634,635,637],"h3",{"id":636},"common-setup-module","Common Setup Module",[71,639,642],{"className":640,"code":641,"language":548},[546],"tests\u002F\n├── common\u002F\n│   └── mod.rs          # NOT a test file\n└── integration_test.rs   # use mod common;\n",[18,643,641],{"__ignoreMap":75},[14,645,646,647,650],{},"Files in ",[18,648,649],{},"tests\u002Fcommon\u002F"," (without a top-level test fn) are helpers, not test binaries.",[23,652,654],{"id":653},"doc-tests","Doc Tests",[67,656,657],{"language":69},[71,658,660],{"className":73,"code":659,"language":69,"meta":75,"style":75},"\u002F\u002F\u002F Adds two numbers.\n\u002F\u002F\u002F\n\u002F\u002F\u002F # Examples\n\u002F\u002F\u002F\n\u002F\u002F\u002F ```\n\u002F\u002F\u002F use my_crate::add;\n\u002F\u002F\u002F assert_eq!(add(2, 2), 4);\n\u002F\u002F\u002F ```\npub fn add(a: i32, b: i32) -> i32 { a + b }\n",[18,661,662,667,672,677,681,686,691,696,700],{"__ignoreMap":75},[79,663,664],{"class":81,"line":82},[79,665,666],{"class":447},"\u002F\u002F\u002F Adds two numbers.\n",[79,668,669],{"class":81,"line":130},[79,670,671],{"class":447},"\u002F\u002F\u002F\n",[79,673,674],{"class":81,"line":137},[79,675,676],{"class":447},"\u002F\u002F\u002F # Examples\n",[79,678,679],{"class":81,"line":143},[79,680,671],{"class":447},[79,682,683],{"class":81,"line":155},[79,684,685],{"class":447},"\u002F\u002F\u002F ```\n",[79,687,688],{"class":81,"line":171},[79,689,690],{"class":447},"\u002F\u002F\u002F use my_crate::add;\n",[79,692,693],{"class":81,"line":176},[79,694,695],{"class":447},"\u002F\u002F\u002F assert_eq!(add(2, 2), 4);\n",[79,697,698],{"class":81,"line":182},[79,699,685],{"class":447},[79,701,702,704,706,708,710,712,714,716,718,720,722,724,726,728,730],{"class":81,"line":194},[79,703,86],{"class":85},[79,705,89],{"class":85},[79,707,93],{"class":92},[79,709,97],{"class":96},[79,711,100],{"class":85},[79,713,103],{"class":92},[79,715,106],{"class":96},[79,717,100],{"class":85},[79,719,103],{"class":92},[79,721,113],{"class":96},[79,723,116],{"class":85},[79,725,103],{"class":92},[79,727,121],{"class":96},[79,729,124],{"class":85},[79,731,127],{"class":96},[389,733,734,740,743],{},[31,735,736,737,408],{},"Compiled and run by ",[18,738,739],{},"cargo test",[31,741,742],{},"Must compile as a separate binary.",[31,744,745,746,100],{},"Hidden imports via ",[18,747,748],{},"#",[67,750,751],{"language":69},[71,752,754],{"className":73,"code":753,"language":69,"meta":75,"style":75},"\u002F\u002F\u002F ```\n\u002F\u002F\u002F # use my_crate::add;\n\u002F\u002F\u002F assert_eq!(add(2, 2), 4);\n\u002F\u002F\u002F ```\n",[18,755,756,760,765,769],{"__ignoreMap":75},[79,757,758],{"class":81,"line":82},[79,759,685],{"class":447},[79,761,762],{"class":81,"line":130},[79,763,764],{"class":447},"\u002F\u002F\u002F # use my_crate::add;\n",[79,766,767],{"class":81,"line":137},[79,768,695],{"class":447},[79,770,771],{"class":81,"line":143},[79,772,685],{"class":447},[14,774,775,776,778],{},"The ",[18,777,748],{}," line is hidden from rendered docs but included when testing.",[634,780,782],{"id":781},"skipping-doc-tests","Skipping Doc Tests",[14,784,785],{},"`::code-wrapper{language=\"text\"}",[71,787,790],{"className":788,"code":789,"language":548,"meta":75},[546],"\u002F\u002F\u002F ```no_run\n\u002F\u002F\u002F loop { \u002F* don't actually run *\u002F }\n\u002F\u002F\u002F ```\n\u002F\u002F\u002F\n\u002F\u002F\u002F ```ignore\n\u002F\u002F\u002F let x = todo!();\n\u002F\u002F\u002F ```\n",[18,791,789],{"__ignoreMap":75},[14,793,794],{},"::`",[14,796,797,800,801,804,805,808,809,812],{},[18,798,799],{},"no_run"," compiles but doesn't execute. ",[18,802,803],{},"ignore"," skips compilation. ",[18,806,807],{},"compile_fail"," asserts the snippet fails to compile (negative tests). ",[18,810,811],{},"rust,no_run"," etc. customize.",[23,814,816],{"id":815},"assertions-cheat-sheet","Assertions Cheat Sheet",[67,818,819],{"language":69},[71,820,822],{"className":73,"code":821,"language":69,"meta":75,"style":75},"assert!(cond);\nassert!(cond, \"custom message {x}\");\nassert_eq!(a, b);\nassert_eq!(a, b, \"msg\");\nassert_ne!(a, b);\ndebug_assert!(cond);          \u002F\u002F only in debug builds\ndebug_assert_eq!(a, b);\n",[18,823,824,831,843,850,862,868,879],{"__ignoreMap":75},[79,825,826,828],{"class":81,"line":82},[79,827,401],{"class":92},[79,829,830],{"class":96},"(cond);\n",[79,832,833,835,838,841],{"class":81,"line":130},[79,834,401],{"class":92},[79,836,837],{"class":96},"(cond, ",[79,839,840],{"class":250},"\"custom message {x}\"",[79,842,222],{"class":96},[79,844,845,847],{"class":81,"line":137},[79,846,404],{"class":92},[79,848,849],{"class":96},"(a, b);\n",[79,851,852,854,857,860],{"class":81,"line":143},[79,853,404],{"class":92},[79,855,856],{"class":96},"(a, b, ",[79,858,859],{"class":250},"\"msg\"",[79,861,222],{"class":96},[79,863,864,866],{"class":81,"line":155},[79,865,407],{"class":92},[79,867,849],{"class":96},[79,869,870,873,876],{"class":81,"line":171},[79,871,872],{"class":92},"debug_assert!",[79,874,875],{"class":96},"(cond);          ",[79,877,878],{"class":447},"\u002F\u002F only in debug builds\n",[79,880,881,884],{"class":81,"line":176},[79,882,883],{"class":92},"debug_assert_eq!",[79,885,849],{"class":96},[14,887,888,889,892,893,896,897,900,901,904,905,907],{},"For ",[18,890,891],{},"Result","-returning assertions, use the ",[18,894,895],{},"matches"," style or ",[18,898,899],{},".unwrap()","\u002F",[18,902,903],{},"?"," with ",[18,906,891],{},"-returning tests.",[23,909,911],{"id":910},"should_panic",[18,912,913],{},"#[should_panic]",[67,915,916],{"language":69},[71,917,919],{"className":73,"code":918,"language":69,"meta":75,"style":75},"#[test]\n#[should_panic]\nfn panics() { panic!(); }\n\n#[test]\n#[should_panic(expected = \"exact substring\")]\nfn panics_specifically() { panic!(\"exact substring here\"); }\n",[18,920,921,925,930,946,950,954,966],{"__ignoreMap":75},[79,922,923],{"class":81,"line":82},[79,924,579],{"class":96},[79,926,927],{"class":81,"line":130},[79,928,929],{"class":96},"#[should_panic]\n",[79,931,932,934,937,940,943],{"class":81,"line":137},[79,933,584],{"class":85},[79,935,936],{"class":92}," panics",[79,938,939],{"class":96},"() { ",[79,941,942],{"class":92},"panic!",[79,944,945],{"class":96},"(); }\n",[79,947,948],{"class":81,"line":143},[79,949,134],{"emptyLinePlaceholder":133},[79,951,952],{"class":81,"line":155},[79,953,579],{"class":96},[79,955,956,959,961,964],{"class":81,"line":171},[79,957,958],{"class":96},"#[should_panic(expected ",[79,960,247],{"class":85},[79,962,963],{"class":250}," \"exact substring\"",[79,965,254],{"class":96},[79,967,968,970,973,975,977,979,982],{"class":81,"line":176},[79,969,584],{"class":85},[79,971,972],{"class":92}," panics_specifically",[79,974,939],{"class":96},[79,976,942],{"class":92},[79,978,200],{"class":96},[79,980,981],{"class":250},"\"exact substring here\"",[79,983,984],{"class":96},"); }\n",[23,986,987],{"id":803},[18,988,989],{},"#[ignore]",[67,991,992],{"language":69},[71,993,995],{"className":73,"code":994,"language":69,"meta":75,"style":75},"#[test]\n#[ignore = \"slow, run manually\"]\nfn slow_test() { \u002F* ... *\u002F }\n",[18,996,997,1001,1014],{"__ignoreMap":75},[79,998,999],{"class":81,"line":82},[79,1000,579],{"class":96},[79,1002,1003,1006,1008,1011],{"class":81,"line":130},[79,1004,1005],{"class":96},"#[ignore ",[79,1007,247],{"class":85},[79,1009,1010],{"class":250}," \"slow, run manually\"",[79,1012,1013],{"class":96},"]\n",[79,1015,1016,1018,1021,1023,1026],{"class":81,"line":137},[79,1017,584],{"class":85},[79,1019,1020],{"class":92}," slow_test",[79,1022,939],{"class":96},[79,1024,1025],{"class":447},"\u002F* ... *\u002F",[79,1027,1028],{"class":96}," }\n",[14,1030,1031,1032,1035],{},"Skipped unless ",[18,1033,1034],{},"--ignored"," is passed.",[23,1037,1039],{"id":1038},"asynchronous-tests","Asynchronous Tests",[67,1041,1042],{"language":69},[71,1043,1045],{"className":73,"code":1044,"language":69,"meta":75,"style":75},"#[tokio::test]\nasync fn async_test() {\n    let v = async_fn().await;\n    assert_eq!(v, 5);\n}\n",[18,1046,1047,1057,1069,1090,1101],{"__ignoreMap":75},[79,1048,1049,1052,1054],{"class":81,"line":82},[79,1050,1051],{"class":96},"#[tokio",[79,1053,365],{"class":85},[79,1055,1056],{"class":96},"test]\n",[79,1058,1059,1062,1064,1067],{"class":81,"line":130},[79,1060,1061],{"class":85},"async",[79,1063,89],{"class":85},[79,1065,1066],{"class":92}," async_test",[79,1068,191],{"class":96},[79,1070,1071,1074,1077,1079,1082,1085,1088],{"class":81,"line":137},[79,1072,1073],{"class":85},"    let",[79,1075,1076],{"class":96}," v ",[79,1078,247],{"class":85},[79,1080,1081],{"class":92}," async_fn",[79,1083,1084],{"class":96},"()",[79,1086,1087],{"class":85},".await",[79,1089,168],{"class":96},[79,1091,1092,1094,1097,1099],{"class":81,"line":143},[79,1093,594],{"class":92},[79,1095,1096],{"class":96},"(v, ",[79,1098,612],{"class":161},[79,1100,222],{"class":96},[79,1102,1103],{"class":81,"line":155},[79,1104,387],{"class":96},[14,1106,1107,1108,211,1111,1114],{},"Use the runtime's test attribute (",[18,1109,1110],{},"tokio::test",[18,1112,1113],{},"async_std::test",").",[23,1116,1118],{"id":1117},"benchmark-tests-unstable","Benchmark Tests (unstable)",[67,1120,1121],{"language":69},[71,1122,1124],{"className":73,"code":1123,"language":69,"meta":75,"style":75},"\u002F\u002F requires nightly or use the `criterion` crate\n#![feature(test)]\nextern crate test;\nuse test::Bencher;\n\n#[bench]\nfn bench_add(b: &mut Bencher) {\n    b.iter(|| add(test::black_box(2), test::black_box(2)));\n}\n",[18,1125,1126,1131,1136,1147,1160,1164,1169,1190,1236],{"__ignoreMap":75},[79,1127,1128],{"class":81,"line":82},[79,1129,1130],{"class":447},"\u002F\u002F requires nightly or use the `criterion` crate\n",[79,1132,1133],{"class":81,"line":130},[79,1134,1135],{"class":96},"#![feature(test)]\n",[79,1137,1138,1141,1144],{"class":81,"line":137},[79,1139,1140],{"class":85},"extern",[79,1142,1143],{"class":85}," crate",[79,1145,1146],{"class":96}," test;\n",[79,1148,1149,1151,1153,1155,1158],{"class":81,"line":143},[79,1150,562],{"class":85},[79,1152,444],{"class":92},[79,1154,365],{"class":85},[79,1156,1157],{"class":92},"Bencher",[79,1159,168],{"class":96},[79,1161,1162],{"class":81,"line":155},[79,1163,134],{"emptyLinePlaceholder":133},[79,1165,1166],{"class":81,"line":171},[79,1167,1168],{"class":96},"#[bench]\n",[79,1170,1171,1173,1176,1179,1181,1184,1187],{"class":81,"line":176},[79,1172,584],{"class":85},[79,1174,1175],{"class":92}," bench_add",[79,1177,1178],{"class":96},"(b",[79,1180,100],{"class":85},[79,1182,1183],{"class":85}," &mut",[79,1185,1186],{"class":92}," Bencher",[79,1188,1189],{"class":96},") {\n",[79,1191,1192,1195,1197,1200,1202,1205,1207,1209,1212,1214,1217,1219,1221,1223,1225,1227,1229,1231,1233],{"class":81,"line":182},[79,1193,1194],{"class":96},"    b",[79,1196,408],{"class":85},[79,1198,1199],{"class":92},"iter",[79,1201,200],{"class":96},[79,1203,1204],{"class":85},"||",[79,1206,93],{"class":92},[79,1208,200],{"class":96},[79,1210,1211],{"class":92},"test",[79,1213,365],{"class":85},[79,1215,1216],{"class":92},"black_box",[79,1218,200],{"class":96},[79,1220,208],{"class":161},[79,1222,216],{"class":96},[79,1224,1211],{"class":92},[79,1226,365],{"class":85},[79,1228,1216],{"class":92},[79,1230,200],{"class":96},[79,1232,208],{"class":161},[79,1234,1235],{"class":96},")));\n",[79,1237,1238],{"class":81,"line":194},[79,1239,387],{"class":96},[14,1241,1242,1245],{},[18,1243,1244],{},"criterion"," is the de facto stable benchmarking tool.",[23,1247,1249],{"id":1248},"property-based-testing","Property-Based Testing",[14,1251,1252,1253,1256,1257,100],{},"Use ",[18,1254,1255],{},"proptest"," or ",[18,1258,1259],{},"quickcheck",[67,1261,1262],{"language":69},[71,1263,1265],{"className":73,"code":1264,"language":69,"meta":75,"style":75},"proptest! {\n    #[test]\n    fn add_commutative(a in -1000i32..1000, b in -1000i32..1000) {\n        proptest::prop_assert_eq!(add(a, b), add(b, a));\n    }\n}\n",[18,1266,1267,1274,1278,1322,1344,1348],{"__ignoreMap":75},[79,1268,1269,1272],{"class":81,"line":82},[79,1270,1271],{"class":92},"proptest!",[79,1273,152],{"class":96},[79,1275,1276],{"class":81,"line":130},[79,1277,179],{"class":96},[79,1279,1280,1282,1285,1288,1291,1294,1297,1300,1303,1305,1308,1310,1312,1314,1316,1318,1320],{"class":81,"line":137},[79,1281,185],{"class":85},[79,1283,1284],{"class":92}," add_commutative",[79,1286,1287],{"class":96},"(a ",[79,1289,1290],{"class":85},"in",[79,1292,1293],{"class":85}," -",[79,1295,1296],{"class":161},"1000",[79,1298,1299],{"class":92},"i32",[79,1301,1302],{"class":85},"..",[79,1304,1296],{"class":161},[79,1306,1307],{"class":96},", b ",[79,1309,1290],{"class":85},[79,1311,1293],{"class":85},[79,1313,1296],{"class":161},[79,1315,1299],{"class":92},[79,1317,1302],{"class":85},[79,1319,1296],{"class":161},[79,1321,1189],{"class":96},[79,1323,1324,1327,1329,1332,1334,1336,1339,1341],{"class":81,"line":143},[79,1325,1326],{"class":92},"        proptest",[79,1328,365],{"class":85},[79,1330,1331],{"class":92},"prop_assert_eq!",[79,1333,200],{"class":96},[79,1335,203],{"class":92},[79,1337,1338],{"class":96},"(a, b), ",[79,1340,203],{"class":92},[79,1342,1343],{"class":96},"(b, a));\n",[79,1345,1346],{"class":81,"line":155},[79,1347,228],{"class":96},[79,1349,1350],{"class":81,"line":171},[79,1351,387],{"class":96},[23,1353,1355],{"id":1354},"snapshot-testing","Snapshot Testing",[14,1357,1252,1358,100],{},[18,1359,1360],{},"insta",[67,1362,1363],{"language":69},[71,1364,1366],{"className":73,"code":1365,"language":69,"meta":75,"style":75},"#[test]\nfn snapshot() {\n    let v = render();\n    insta::assert_snapshot!(v);\n}\n",[18,1367,1368,1372,1381,1395,1408],{"__ignoreMap":75},[79,1369,1370],{"class":81,"line":82},[79,1371,579],{"class":96},[79,1373,1374,1376,1379],{"class":81,"line":130},[79,1375,584],{"class":85},[79,1377,1378],{"class":92}," snapshot",[79,1380,191],{"class":96},[79,1382,1383,1385,1387,1389,1392],{"class":81,"line":137},[79,1384,1073],{"class":85},[79,1386,1076],{"class":96},[79,1388,247],{"class":85},[79,1390,1391],{"class":92}," render",[79,1393,1394],{"class":96},"();\n",[79,1396,1397,1400,1402,1405],{"class":81,"line":143},[79,1398,1399],{"class":92},"    insta",[79,1401,365],{"class":85},[79,1403,1404],{"class":92},"assert_snapshot!",[79,1406,1407],{"class":96},"(v);\n",[79,1409,1410],{"class":81,"line":155},[79,1411,387],{"class":96},[23,1413,1415],{"id":1414},"test-organization-tips","Test Organization Tips",[389,1417,1418,1424,1427,1430],{},[31,1419,1420,1421,1423],{},"Unit tests inside ",[18,1422,40],{}," so they don't bloat the production binary.",[31,1425,1426],{},"Don't test private functions if you can test them through the public API.",[31,1428,1429],{},"Test edge cases: empty, boundary, max\u002Fmin, overflow, unicode, concurrency.",[31,1431,1252,1432,1435],{},[18,1433,1434],{},"mockall"," or hand-rolled traits for dependency injection.",[23,1437,1439],{"id":1438},"common-pitfalls","Common Pitfalls",[389,1441,1442,1450,1462,1482,1491,1500,1513,1528],{},[31,1443,1444,1449],{},[34,1445,1446],{},[18,1447,1448],{},"#[should_panic(expected = ...)]"," is a substring match, not regex\u002Fexact.",[31,1451,1452,1457,1458,1461],{},[34,1453,1454,1456],{},[18,1455,739],{}," runs in parallel by default",": shared files \u002F ports can race. Use ",[18,1459,1460],{},"--test-threads=1"," or unique tempdirs.",[31,1463,1464,1471,1472,1474,1475,900,1478,1481],{},[34,1465,1466,1467,1470],{},"Tests in ",[18,1468,1469],{},"bin\u002F"," files",": put ",[18,1473,40],{}," in ",[18,1476,1477],{},"main.rs",[18,1479,1480],{},"bin\u002Fx.rs"," too.",[31,1483,1484,1487,1488,1114],{},[34,1485,1486],{},"Doc tests slow",": many crates skip them in CI for speed (",[18,1489,1490],{},"cargo test --lib --bins --tests",[31,1492,1493,1499],{},[34,1494,1495,1498],{},[18,1496,1497],{},"unwrap()"," in tests is fine",": tests aren't production code; panicking is OK.",[31,1501,1502,1505,1506,1509,1510,408],{},[34,1503,1504],{},"Floating point equality",": use ",[18,1507,1508],{},"approx"," crate or ",[18,1511,1512],{},"assert!((a - b).abs() \u003C EPS)",[31,1514,1515,1505,1520,1523,1524,1527],{},[34,1516,1517,1519],{},[18,1518,739],{}," shows only failures by default",[18,1521,1522],{},"--nocapture"," to see ",[18,1525,1526],{},"println!"," output even on success.",[31,1529,1530,1533,1534,1537],{},[34,1531,1532],{},"Time-sensitive tests",": inject a ",[18,1535,1536],{},"Clock"," trait for deterministic tests.",[23,1539,1541],{"id":1540},"coverage","Coverage",[67,1543,1544],{"language":431},[71,1545,1547],{"className":434,"code":1546,"language":431,"meta":75,"style":75},"cargo install cargo-tarpaulin\ncargo tarpaulin\n",[18,1548,1549,1559],{"__ignoreMap":75},[79,1550,1551,1553,1556],{"class":81,"line":82},[79,1552,20],{"class":92},[79,1554,1555],{"class":250}," install",[79,1557,1558],{"class":250}," cargo-tarpaulin\n",[79,1560,1561,1563],{"class":81,"line":130},[79,1562,20],{"class":92},[79,1564,1565],{"class":250}," tarpaulin\n",[14,1567,1568,1569,1572],{},"Or ",[18,1570,1571],{},"cargo-llvm-cov"," for source-based coverage.",[23,1574,1576],{"id":1575},"fuzzing","Fuzzing",[14,1578,1252,1579,1582],{},[18,1580,1581],{},"cargo-fuzz"," (libFuzzer-based) for finding panics\u002FUB:",[67,1584,1585],{"language":431},[71,1586,1588],{"className":434,"code":1587,"language":431,"meta":75,"style":75},"cargo install cargo-fuzz\ncargo fuzz add parse_target\n# edit fuzz\u002Ffuzz_targets\u002Fparse_target.rs\ncargo fuzz run parse_target\n",[18,1589,1590,1599,1611,1616],{"__ignoreMap":75},[79,1591,1592,1594,1596],{"class":81,"line":82},[79,1593,20],{"class":92},[79,1595,1555],{"class":250},[79,1597,1598],{"class":250}," cargo-fuzz\n",[79,1600,1601,1603,1606,1608],{"class":81,"line":130},[79,1602,20],{"class":92},[79,1604,1605],{"class":250}," fuzz",[79,1607,93],{"class":250},[79,1609,1610],{"class":250}," parse_target\n",[79,1612,1613],{"class":81,"line":137},[79,1614,1615],{"class":447},"# edit fuzz\u002Ffuzz_targets\u002Fparse_target.rs\n",[79,1617,1618,1620,1622,1625],{"class":81,"line":143},[79,1619,20],{"class":92},[79,1621,1605],{"class":250},[79,1623,1624],{"class":250}," run",[79,1626,1610],{"class":250},[23,1628,1630,1633,1634,1637,1638],{"id":1629},"test-traits-debug-for-assert_eq",[18,1631,1632],{},"Test Traits",": ",[18,1635,1636],{},"Debug"," for ",[18,1639,404],{},[14,1641,1642,1644,1645,1648],{},[18,1643,404],{}," requires ",[18,1646,1647],{},"T: PartialEq + Debug",". If you see \"the trait Debug is not implemented,\" derive it.",[23,1650,1652],{"id":1651},"summary","Summary",[14,1654,1655,1656,1659,1660,1662,1663,900,1665,900,1667,900,1669,1671,1672,1674,1675,1677,1678,900,1680,900,1682,900,1684,1686],{},"Tests live alongside code (",[18,1657,1658],{},"#[cfg(test)]","), in ",[18,1661,50],{}," for integration, and in doc comments for doc tests. Use ",[18,1664,401],{},[18,1666,404],{},[18,1668,910],{},[18,1670,989],{},". Run with ",[18,1673,739],{},". Use ",[18,1676,1110],{}," for async. Use ",[18,1679,1255],{},[18,1681,1360],{},[18,1683,1244],{},[18,1685,1581],{}," for advanced testing.",[14,1688,1689],{},"Next: Concurrency, threads, and the message-passing vs shared-state story.",[1691,1692,1693],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}",{"title":75,"searchDepth":130,"depth":130,"links":1695},[1696,1697,1698,1699,1702,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1718],{"id":25,"depth":130,"text":26},{"id":64,"depth":130,"text":65},{"id":427,"depth":130,"text":428},{"id":541,"depth":130,"text":542,"children":1700},[1701],{"id":636,"depth":137,"text":637},{"id":653,"depth":130,"text":654,"children":1703},[1704],{"id":781,"depth":137,"text":782},{"id":815,"depth":130,"text":816},{"id":910,"depth":130,"text":913},{"id":803,"depth":130,"text":989},{"id":1038,"depth":130,"text":1039},{"id":1117,"depth":130,"text":1118},{"id":1248,"depth":130,"text":1249},{"id":1354,"depth":130,"text":1355},{"id":1414,"depth":130,"text":1415},{"id":1438,"depth":130,"text":1439},{"id":1540,"depth":130,"text":1541},{"id":1575,"depth":130,"text":1576},{"id":1629,"depth":130,"text":1717},"Test Traits: Debug for assert_eq!",{"id":1651,"depth":130,"text":1652},"Rust's testing is built into the language and cargo. There are three layers: unit tests, integration tests, and documentation tests.","md",{},"\u002Frust\u002F21-testing",{"title":5,"description":1719},"rust\u002F21-testing","QZc7Fu_U7wAQFS-HUolUjeAFtOzYrEOtwFvoFRdRcCQ",1785944093256]