Fixtures
Learn how to inject data into and perform activities before and after your tests.
We'll cover the following...
What is a fixture?
Merriam-Webster’s dictionary defines a fixture as “a device for supporting work during machining.” This definition is pretty close to what we mean when we talk about fixtures in software testing. We can think of test fixtures as boundary conditions or preconditions that have to be verified for a test to begin. Many people think a test fixture is all the system setup you need for tests to run. That’s exactly what preconditions are—something that must be true at the beginning of a flow.
Classic fixture examples include database connections, sockets, and files. But they can also be simple objects or values that we use in our tests. If a test is based on an external value, that means the value must already be there, initialized as expected, for the test to run. We’ve been using fixtures in our code samples so far without even realizing it. Remember the EducativeSpec
class? Let’s take a look at an extract.
package mdipirro.educative.io.effectiveunitandintegrationtestinginscala.matchers import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.TestSuite import mdipirro.educative.io.effectiveunitandintegrationtestinginscala.model.v2.{Author, Educative, FreeCourse, Lesson} class EducativeSpec extends TestSuite: private val educative = Educative(Seq( FreeCourse("Scala for Beginners", Author("John", "Doe"), Set.empty[Lesson], Set.empty[String]), FreeCourse("Scala for Data Analysis", Author("Mary", "Jane"), Set.empty[Lesson], Set("Scala")), FreeCourse("Functional Kotlin", Author("Mary", "Jane"), Set.empty[Lesson], Set("kotlin")) )) "The Educative platform" `should` "filter the courses by tag" in { val scalaCoursesTags = educative.filterByTag("Scala") map (_.tags) all(scalaCoursesTags) should contain ("Scala") }
In this example, educative
(line 8) is a fixture. The test case shown above won’t run if educative
isn’t initialized properly. However, scalaCoursesTags
(line 15) isn’t a fixture. It’s simply a temporary value we introduced in the body of our test to enhance code readability.
When a fixture is needed by more than one test, it’s good practice to avoid code duplication. In EducativeSpec
we could have duplicated the educative
initialization in every test case. This is a very bad practice, however, because the more code duplication we have in our tests and application code, the more difficult it will be to maintain that code.
Usually, we take great care to avoid duplication in applicative code. But tests are another story. Normally, developers couldn’t care less about tests, even though they’re as important as the applicative code. Spaghetti tests will lead to a drop in productivity because refactoring or extending applicative code often means refactoring or extending your tests.
In this lesson, we’ll take a look at several ways to define well-designed fixtures in our tests. Each ...