Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

Get unlimited access to all of Medium for less than $1/week.

Become a member

Open in app

8 Tips for Writing Better Unit Tests


Fotis Adamakis · Follow
4 min read · Jun 17

Listen Share More

U nit tests are an essential part of every successful software application.


They help identify bugs early and ensure that the code is working as
expected. Let me list some widely adopted key strategies that can help you write
bet t er code and improve t he qualit y of your codebase.

1. Arrange, Act, and Assert


The Arrange, Act, and Assert (AAA) is a widely used technique in unit testing. It
involves breaking down a test into three distinct phases:

1. Arranging the test data.

2. Performing the Act ion or method call.

3. Assert ing the results.


To apply the AAA pattern, you should first arrange the test by setting up the
necessary mocks and component instance. Then, you should act by performing
the action or method call that you want to test. Finally, you should assert the
results by checking that the output of the method call matches the expected
output.

For example, given the following simple counter component written in Vue
Options API:

// Counter.vue
export default {
data() {
return {
counter: 0
}
}, 4
methods: {
increment() {
this.counter++
}
}
}

Testing it with the AAA approach is pretty straightforward:

// Counter.spec.js
import { shallowMount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'

describe('Counter.vue', () => {
it('increments the counter when the increment method is called', () => {
// Arrange
const wrapper = shallowMount(Counter)

// Act
wrapper.vm.increment()

// Assert
expect(wrapper.vm.counter).toBe(1)
})
})
2. Descriptive Names and Descriptions
Clear and concise test names and descriptions are essential for effectively
communicating the purpose and scope of the test and making it easier to
understand and maintain them.

To write good test names and descriptions, you should use descript ive and
meaningful names that accurately reflect the purpose of the test. You should
also include relevant details in the description, such as the input data and
expected output.

For example, a lazily written title gives little information about the test case:

describe('Counter.vue', () => {
it('increment', () => {
...
})
})

In contrast, when one of the following fails, the problem will be apparent.

describe('Counter.vue', () => {
it('increments the counter when the increase button is pressed', () => {
...
})
it('prevents the counter value of being negative when the counter is zero and the
...
})
})

3. Fast
Unit tests should be fast to ensure a seamless development workflow. Quick test
execution allows for prompt feedback, making it easier to identify and fix issues.
To create speedy tests, avoid external dependencies and minimize I/O operations.
Utilize mocks and stubs to simulate dependencies and focus on testing small,
isolated pieces of code.

4. Deterministic
Deterministic tests are tests that produce t he same output every t ime t hey are
run. They are important because they help ensure that the tests are reliable and
repeat able. To write deterministic tests, avoid using random data and external
sources that can change. Use repeatable inputs and keep test environments
consistent. Also, avoid using shared global resources that other tests can modify.

5. Comprehensive
A well-rounded unit test assesses both successful execution and potential
failures (happy & unhappy paths). It’s vital to test functions using valid inputs to
confirm expected results and invalid inputs to identify potential issues.
Furthermore, validate error handling by examining proper responses to thrown
exceptions during path execution.

6. Test-driven Development
Test-driven development (TDD) is a technique of writing tests before or during
the development process. It ensures that the code is testable and that the tests
cover all the necessary scenarios.

To implement TDD, start by writing a failing test that covers a specific scenario
or requirement. Then, write the minimum amount of code necessary to pass the
test. Finally, refactor the code to improve its design and maintainability.

7. Using Mocks
Mocks simulate the behaviour of external dependencies or objects. They are
important because they help isolate the code being tested and make it easier to
write deterministic tests.

To use mocks efficiently, start by identifying external dependencies that must be


mocked. Then, generate a mock/stub object that mimics the behaviour of the
dependency. This provides full control of returned values and the ability to track
invocations and their associated parameters.

8. Run on CI/CD
By integrating unit tests into your development pipeline and ensuring their
successful execution, you can prevent potential issues from slipping into
production environments.

Conclusion
Treating unit t est s as first-class cit izens means giving them the same level of
importance as production code. This mindset ensures that tests are consistently
written, well-maintained, and updated as necessary.

Taking the time to invest in proper unit testing techniques will save you time and
effort in the long run and result in more robust and efficient applications.

Unit Testing Testing Software Development Programming Software Testing


Follow

Written by Fotis Adamakis


938 Followers

« Senior Software Engineer @ Glovo · Author · International Speaker · Vue.js Athens Meetup Organizer »

More from Fotis Adamakis

Fotis Adamakis

Stop Over-Engineering your Medium Size Front-End Application


Writing maintainable code without falling into the trap of over-engineering has become
increasingly uncommon in the field of programming

6 min read · Jun 16

246 3
Fotis Adamakis

[Vue 3] Why both Ref and Reactive are needed


Declaring Reactive Data while working with the Options API was straightforward. Everything
inside the data option was automatically made…

3 min read · Jul 19

62 2

Fotis Adamakis
Advanced Data Fetching with Vue Query
A Must-Have Library for Every Vue Codebase

6 min read · Jun 11

74 1

Fotis Adamakis

It’s 2023. Start using JavaScript Maps and Sets


As a JavaScript developer, you are probably familiar with the two most commonly used data
structures, Arrays and Objects. They are both…

3 min read · May 9

283 2

See all from Fotis Adamakis

Recommended from Medium


Rico Fritzsche in Level Up Coding

Microservices: The Million-Dollar Mistake Your Company is Making


In the middle of the last decade, as I was elbow-deep in code, tinkering with concepts like
service discovery, a buzzword began to echo…

· 5 min read · Jul 11

684 24

Ignacio de Gregorio
Microsoft Just Showed us the Future of ChatGPT with LongNet
Let’s talk about Billions

· 8 min read · Jul 20

2.1K 32

Lists

General Coding Knowledge


20 stories · 112 saves

It's never too late or early to start something


13 stories · 44 saves

Coding & Development


11 stories · 71 saves

Stories to Help You Grow as a Software Developer


19 stories · 202 saves

Daley Wilhelm in UX Collective

So… did Netflix win?


In the case of the Netflix password crackdown, did ease of use win over user outrage?
· 4 min read · Jul 20

1.2K 44

Yang Zhou in TechToFreedom

My First 10 Years of Programming


And how my life has been changed so much

· 13 min read · 4 days ago

595 10
Apoorva in Mac O’Clock

Top 5 New MacOS Apps for Maximum Productivity


Boost your productivity

· 6 min read · Feb 23

468 7

Cole in Cantor’s Paradise

The Beauty of Simple Cellular Automata


You may have heard of Stephen Wolfram, founder of WolframAlpha and the math-based
programming language Mathematica. Wolfram likes to ask…

· 9 min read · Jul 21

408 4

See more recommendations

You might also like