Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Software Testing in Rust for Developers

Posted on Sep 23 In this guide, we will learn what tests are and how to write and run them in Rust. This article is designed to be simple, straightforward, and to the point. It includes Code snippets with comments to demonstrate how each concept appears in actual code. Please note that these code snippets may not compile.Before we proceed, it's assumed that you have a basic understanding of testing principles and Rust, including its module system. Therefore, I won't be providing explanations of these concepts throughout the article.A function annotated with a test attribute is a Test in Rust, It can also be called a Test Function.This test attribute (#[test]) indicates that the following function is a Test Function, not a normal function.How to make a Test Fail or PassTest "fails" when the Test Function "panics"We can call panic! macro explicitly or other code within our test function can invoke the panic! macro to mark a test as "failed"Test "passes" when the Test Function finishes execution without any panics.Run your TestsWe can run cargo test command to run our tests. It will run all the test functions and show the result of the tests.cargo testTo run specific tests, We can provide the "name" or a "part of the name" of the test(s) to the cargo test command. Cargo will then run all the tests whose names contain the given text.cargo test Where to Write TestsThe simplest way to organize our tests is by putting them in the same file with the code they test. When we follow this approach, Rust will compile the tests along with the regular code when we run cargo build or cargo run, which is not desirable.To solve this, We create a module named "tests" in the same file to contain all the tests.then, Add #[cfg(test)] attribute to the "tests" module, this attribute tells Rust to compile and run this module code only when we run the cargo test command.Now, when we write tests, we will notice that code outside of the tests module is not in scope and we are unable to use it. To use outside code, We have to bring it into the scope of the current module. We do this by using use super::* statement.Below code snippet shows an example of tests written with the regular code -To understand the above code snippet more, see the image below -Assertion Utilitiesassert! macroThe assert! macro takes an expression as a first parameter and checks if that expression evaluates to true.If the given expression doesn't evaluate to true, assert! macro will invoke panic! macro for us and the test will be marked as failed.assert_eq! macroThe assert_eq! macro checks if the two expressions are equal to each other using double equal comparison (== operator).If the two expressions are not equal, assert_eq! macro will invoke panic! macro for us and the test will be marked as failed.assert_ne! macroThe assert_ne! macro is the opposite of assert_eq! macro.Instead of checking for equality, It checks if the two expressions are not equal to each other using a "not equal" comparison (!= operator).If the two expressions are equal, assert_ne! macro will invoke panic! macro and the test will be marked as failed.should_panic attributeThe should_panic attribute allows us to verify whether the code inside the test function triggers the panic! macro when expected, enabling us to test the occurrence of panics.When the code inside the test function invokes panic! macro, our test is not marked as failed, the should_panic attribute marks the test as "passed" because panic was expected.To add the should_panic attribute to a function, we can simply place it on a new line after the test attribute. Refer to below code snippet -In Rust, panic can be triggered for various reasons. With should_panic attribute, we can also check if a panic was triggered for a specific reason.If the panic happens as expected for that reason, the test will pass. However, the test will be marked as failed if the panic occurs for a different reason or doesn't happen at all.Refer to below code snippet for example -The assert!, assert_eq! and assert_ne! macros also allow us to provide custom error messages. When these macros invoke panic! macro, they pass along the custom message we provided. This helps us to provide descriptive error messages when a test fails.After providing the required parameters to the assert!, assert_eq!, and assert_ne! macros, we can pass a custom error message. Any additional arguments provided after the custom message will be passed to the placeholders("{}") present in the error message string, allowing us to create more detailed and dynamic error messages.Refer to below code snippet for usage examples -Organizing Integration TestsIn the "Where to Write Tests" section, we discussed where to put our tests. However, that applies only to unit tests and not Integration tests.In Rust, Integration tests are for testing "library crates" and not binary crates, using our library crate as any other external code would. This means in integration tests, we can only use public functions of our library crate.To write Integration tests -We first need to create a "tests" directory at the root of the crate next to the "src" directory.In this directory, we can create as many test files as we want, Rust knows to look for integration tests in files inside the "tests" directory.Then we need to bring our library crate into the scope of each test file usinguse ::* statement at the top of the file because each file will be a separate crate.Bonus 🎁By default, If a test passes, println! statement used inside it, will not print anything to the console. However, we can change this behaviour with --nocapture flag.# Example of--nocapture` flag usagecargo test -- --nocapture`We can also use Result struct instead of triggering a panic.Instead of using assert!, assert_eq!, assert_ne! macros or calling panic! macro explicitly, we can return Result::Err variant when we want the test to fail or Result::OK variant when we want the test to pass.SummaryAnnotate functions with #[test] attribute to make them test functions."Triggering a panic in the test function" or "returning a Result::Err variant from the test function" will make the test fail.Use cargo test command to run tests, additionally, we can pass the name of the test - cargo test We can put our unit tests in the same file as the regular code.We put unit tests in a module annotated with #[cfg(test)] attribute. Inside the module, we use use super::* statement to bring the parent module code into the current module's scope.We can use assert!, assert_eq! and assert_ne! macros, instead of triggering panic ourselves.We can use should_panic! macro when we expect panic to be triggered in a test.Integration tests are written in a separate directory named "tests" at the root level of our project. Since Integration tests are separate from the library code, we need to bring the library into scope explicitly.**Before We End.**..Thank you for reading! I hope you learned something from this guide.If you want to dive deeper into testing in Rust, I recommend checking out the official Rust book on https://doc.rust-lang.org/book/ch11-00-testing.htmlIf you found this guide helpful, please share and like it to help more people discover it.Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse PARMITA UPADHYAY - Sep 7 Nikita Koselev - Sep 6 Kinanee Samson - Sep 17 Antonov Mike - Sep 4 Once suspended, talenttinaapi will not be able to comment or publish posts until their suspension is removed. Once unsuspended, talenttinaapi will be able to comment and publish posts again. Once unpublished, all posts by talenttinaapi will become hidden and only accessible to themselves. If talenttinaapi is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to talent. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag talenttinaapi: talenttinaapi consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging talenttinaapi will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Software Testing in Rust for Developers

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×