DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Unit Testing Large Codebases: Principles, Practices, and C++ Examples
  • Practical Use of Weak Symbols
  • Generate Unit Tests With AI Using Ollama and Spring Boot
  • Understanding the Two Schools of Unit Testing

Trending

  • A Simple, Convenience Package for the Azure Cosmos DB Go SDK
  • AI’s Role in Everyday Development
  • AWS to Azure Migration: A Cloudy Journey of Challenges and Triumphs
  • Agile and Quality Engineering: A Holistic Perspective
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Testing, Tools, and Frameworks
  4. Writing Your F.I.R.S.T Unit Tests

Writing Your F.I.R.S.T Unit Tests

First class developers write their code test-first using FIRST. Tests should be fast, independent, repeatable, self-validating, and timely.

By 
Dan Newton user avatar
Dan Newton
·
Mar. 17, 17 · Tutorial
Likes (8)
Comment
Save
Tweet
Share
50.8K Views

Join the DZone community and get the full member experience.

Join For Free

Unit tests are required to test singular sections of code. In Java, this would normally be a class. They provide confidence to programmers, allowing changes to be made. And by running tests throughout development, any changes that break the tests can be re-evaluated, whether that results in the production code being corrected or altering the test to make it pass. In this post, I will discuss the FIRST rules that are defined in the book Clean Code written by Uncle Bob Martin.

Related: How to Unit Test Java Stream Pipelines

FIRST means that tests should be:

  • Fast: Tests should be fast enough that you won't be discouraged from using them. If you are making changes to a class or method that has a few tests attached to them, you are much more likely to run those tests after making changes if they take about a second to run, compared to slower tests that cannot only take a while to initialize, but each test case could also take over 1 second to run. For example, I have run integration tests that would take 20+ seconds to run and I hated having to run them after code changes. Unit tests, however, do not have to test multiple components like integration tests do and, therefore, keeping them running in under 1 second should be possible. DZone's previously covered how to implement the cucumber framework with Spring Boot integration tests.
  • Independent: Tests should not depend on the state of the previous test, whether that is the state of an object or mocked methods. This allows you to run each test individually when needed, which is likely to happen if a test breaks, as you will want to debug into the method and not have to run the other tests before you can see what is going wrong. If you have a test that is looking for the existence of some data, then that data should be created in the setup of the test and preferably removed afterward so as not to affect the later tests.
  • Repeatable: Tests should be repeatable in any environment without varying results. If they do not depend on a network or database, then it removes the possible reasons for tests failing, as the only thing they depend on is the code in the class or method that is being tested. If the test fails, then the method is not working correctly or the test is set up wrong — and nothing else.
  • Self-validating: Each test will have a single boolean output of pass or fail. It should not be up to you to check whether the output of the method is correct each time the test is run. The test should tell you if the result of the test was valid or not. This is normally done using asserts such as assertTrue or assertEquals, which will cause the test to pass or fail depending on their results.
  • Timely: Unit tests should be written just before the production code that makes the test pass. This is something that you would follow if you were doing TDD (Test Driven Development), but otherwise it might not apply. I personally do not use TDD and therefore I always write my tests after writing my production code. Although I can see the reasons for following this, I believe this is the rule that could be skipped if not appropriate.

Testing Tutorial: How to Setup Cypress Tests in Azure DevOps Pipeline

Below is a little unit test that I wrote that follows the rules above. Please note that this is just a simple test, and if you think there are scenarios that are being not tested, you are correct! (But the example is long enough already.)

@RunWith(JUnit4.class)
public class PersonValidatorTest {

    private PersonValidator testSubject = new PersonValidator();

    private Person person;

    @Test
    public void personCalledDanNewtonIsNotValid() {
        person = new Person("Dan","Newton",23,1000);
        assertFalse(testSubject.isValid(person));
    }

    @Test
    public void personNotCalledDanNewtonIsValid() {
        person = new Person("Bob","Martin",60,170);
        assertTrue(testSubject.isValid(person));
    }

    @Test
    public void personIsOlderThanTwentyFiveIsValid() {
        person = new Person("Bob","Martin",60,170);
        assertTrue(testSubject.isValid(person));
    }

    @Test
    public void personIsYoungerThanTwentyFiveIsNotValid() {
        person = new Person("Bob","Martin",10,170);
        assertFalse(testSubject.isValid(person));
    }

    @Test
    public void personIsTwentyFiveIsNotValid() {
        person = new Person("Bob","Martin",25,170);
        assertFalse(testSubject.isValid(person));
    }
}
public class PersonValidator {

    public boolean isValid(final Person person) {
        return isNotCalledDanNewton(person) && person.getAge() > 25 && person.getHeight() < 180;

    }

    private boolean isNotCalledDanNewton(final Person person) {
        return !person.getFirstName().equals("Dan") || !person.getLastName().equals("Newton");
    }

}

So do these tests follow FIRST?

  • Fast: They do not do much, so obviously they are quick to run.
  • Independent: Each test sets up a new person and passes in all the parameters that are required for the test.
  • Repeatable: This test does not depend on any other classes or require a connection to a network or database.
  • Self-validating: Each test has a single assert, which will determine whether the test passes or fails.
  • Timely: Failure!! I did not write these tests before writing the code in PersonValidator, but again, this is because I do not use TDD.

By following the FIRST rules in this post, your unit tests should see some improvement. I am not saying that following these rules alone will make your unit tests perfect, as there are still other factors that come into making a good test, but you will have a good foundation to build upon.

unit test

Published at DZone with permission of Dan Newton, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Unit Testing Large Codebases: Principles, Practices, and C++ Examples
  • Practical Use of Weak Symbols
  • Generate Unit Tests With AI Using Ollama and Spring Boot
  • Understanding the Two Schools of Unit Testing

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!