avatarMichael Henderson

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

4642

Abstract

Long Run</h1><p id="c33f">Some developers argue that manual testing is the best way to test applications because the costs are lower. These individuals argue what I like to call the <i>cost-point argument.</i></p><p id="ba84">You see, that is the reason most people give when they compare the amount of time it takes to complete something.</p><p id="1c92">Spend time and money doing it the right way now so time and money are not wasted trying to do the right thing at the wrong time later.</p><p id="fb74">With automated testing, you create a separate project for writing tests. In that project, you’ll write code and directly call the functions with different inputs and verify the functions return the right output.</p><p id="aec3">As you can see, it does take more time to write the test for your application, but as your project scales and obtains more moving parts, you will eventually increase the cost and take more time to test your application if you are not using automation.</p><h1 id="247e">Tests With Benefits</h1><p id="0c02">The good thing about automated tests is they are reusable. You write them once and run them a million times.</p><p id="8cc2">Lots of teams find it beneficial to run their tests with every commit. With this approach, it makes sure breaking changes are caught way before a pull request is accepted into the master branch.</p><p id="48d6">I personally like to give the team one command to run that does linting and testing in one go.</p><p id="95be">The devs know to run it before opening a pr because if there is a lint error or a test fails, the CI/CD system will flag the pull request and block it from being merged.</p><p id="39bf">No breaking change in production is the goal.</p><p id="78aa">With this approach, you can test all the execution paths in the functions of the app in a fraction of a second.</p><p id="315e">Writing automated tests also helps you write better code. When writing tests, you’re forced to think about the edge cases of every function in your application. You write tests for these functions, giving them various inputs and make sure they behave as you expect.</p><p id="3af2">This will help you produce better-quality software with fewer defects. A lot of bugs in our applications are the result of unforeseen edge cases. One of your functions receives an input that you forgot to predict … and boom!</p><p id="a7d3">It blows up faster than my writing career!</p><p id="d29e">With automated tests, you make sure that every function works with different inputs under varying circumstances, and those meddling bugs stay out of production.</p><h1 id="0b20">Types of Tests</h1><p id="b1ac">There are many different types of tests, but the three I am focusing on in this piece are:</p><ol><li>Unit</li><li>Integration</li><li>End-to-end</li></ol><p id="580a">Remember, no one test fits all. You may use different types of tests depending on the type of application you’re building and the amount of coverage your team prefers.</p><p id="0cc0">We will go over these in a bit. For now, just know that there are three different types of tests that we can perform on the parts of an application.</p><h2 id="bf6c">Unit testing</h2><p id="83df">Unit tests, a growing trend among software developers, determine whether certain sections of the code are acting as predicted under different circumstances.</p><p id="3b58">In the context of single-page applications, unit testing is only going to focus on the component. If we have a failure in the template, then we’ll not know until runtime. Unit tests are fast and not as complex to write, but they don’t give us much predictability about the application.</p><p id="577f">In Angular terms, it tests certain components of the application without its template and many other external resources like file systems, databases, and API endpoints.</p><p id="626c">For example, in an Angular app, we have templates, services, and other pieces of our application that tie into our components.</p><p id="bead">A unit test would test just the components of our Angular app without touching templates, services, etc.</p><p id="0261">If your component does rely on a service, we will give it a fake instance of that service. Similarly, if your component relies on a router, you will give it a fake instance of that router.</p><p id="1f0c">In unit testing, we assume that the service and router are doing their jobs. So this allows us to focus on the component to ensure it’s working correctly. Let’s dive into some code to get a better understanding of how a unit test works.</p><div id="871f"><pre><span class="hljs-keyword">export</span> <span c

Options

lass="hljs-keyword">class</span> <span class="hljs-title class_">VoteComponent</span> {
totalVotes: number; </pre></div><div id="1287"><pre> <span class="hljs-title function_">upVote</span>(<span class="hljs-params"></span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">totalVotes</span>++;
} }</pre></div><p id="ec4a">Above is our component, which is basically a simple TypeScript class. The <code>totalVotes</code> property will change every time the <code>upVote()</code> method is called.</p><p id="0f3b">Let's assume we have a button inside a template that calls the <code>upVote()</code> method like this:</p><div id="53c6"><pre><span class="hljs-template-variable">{{ <span class="hljs-name">totalVotes</span> }}</span><span class="language-xml"><span class="hljs-tag"><<span class="hljs-name">button</span> (<span class="hljs-attr">click</span>)=<span class="hljs-string">"upVote()"</span>></span>up<span class="hljs-tag"></<span class="hljs-name">button</span>></span></span></pre></div><p id="0440">When the button is clicked, we expect the <code>upVote</code> method to be called and the <code>totalVotes</code> property should increment by 1.</p><p id="a1eb">If the test notices different behavior, it’s flagged — and the developer can go fix it.</p><h2 id="1dfd">Integration test</h2><p id="1e18">Integration testing gives the ability to test a component with external resources.</p><p id="71c9">Remember our <code>VoteComponent</code>? Integration tests have the ability to treat our <code>VoteComponent</code> as an Angular component.</p><p id="0d5e">To better understand this and since the integration test also tests external resources, we need to run it in an Angular environment.</p><p id="d2cb">Maybe there are certain build outcomes and environments you need to test the app in and expect a certain outcome — integration tests will handle it.</p><p id="c201">In this situation, we need to instruct Angular to compile our <code>VoteComponent</code> and its template together. So the test is aware of the two.</p><p id="7d39">There is more test code to write since we have to run this in an Angular environment, but we’ll gain more confidence about the functionality of our component because the tests will run our app with the awareness of the template and component that compose the template.</p><p id="d77d">Now, similar to unit testing, we’ll still provide a fake service to this component.</p><p id="0e18">While integration tests are more reliable, they are still fragile because we are only testing a few parts of our application: the component and template.</p><p id="32fc">This type of test doesn’t look at our application as a whole.</p><h2 id="8f23">End-to-end test</h2><p id="d6a1">This type of test will launch the application, test logins, fill out contact forms, etc.</p><p id="3b48">This allows us to have more confidence in the software we release, but end-to-end tests are slow and fragile.</p><p id="119f">They are slow because of all the mechanics behind the tests themselves and the high percentage of code that is covered.</p><p id="46cb">With the end-to-end test, we test the entire application as a whole.</p><p id="2ded">It takes time for the test to run because it’s going to simulate a live user. They are fragile because one change to the HTML in a template could throw off the entire test.</p><p id="bd0d">For every change you make to the application, you have to adjust the test code works correctly.</p><p id="f963">End-to-end tests are only for key parts of the application. This is actually great in some scenarios.</p><h1 id="11e8">Conclusion</h1><p id="c2c5">Now that you understand the different types of tests, the pros and cons of them, when to use them, and how they work, you now have the basics to dive into learning one of the different ways to test.</p><p id="9126">No matter the type of testing you use, I promise you will build quality software and see fewer bugs in production.</p><p id="257f">Unit tests are easier to write, so I suggest starting there.</p><p id="a122">Just remember, no one test fits every scenario. There are situations where you would use one over the other.</p><p id="fb88">Cheers!</p><p id="33b7"><i>Consider becoming a <a href="https://medium.com/@michaelhenderson/membership">Medium member</a> if you appreciate reading stories like this and want to help me as a writer. It cost $5 per month and gives you unlimited access to Medium. I’ll get a little commission if you sign up via <a href="https://medium.com/@michaelhenderson/membership">my link</a>.</i></p></article></body>

Automated Testing and Why You Should Use It

Let’s talk about automated testing methods like unit tests, end-to-end tests, and integration tests

Photo by David Travis on Unsplash

If you’re a senior developer, you must know how to write tests. Don’t know how? Then you’re probably more of an intermediate-level developer, even if you have a senior position at your company.

If you’re a junior/intermediate-level developer and want to become a senior developer, you must have unit testing on your resume to get a better job. Most good companies with good programmers practice unit testing these days.

“Quality is never an accident; it is always the result of intelligent effort.” — John Ruskin

By the end of this article, we’ll have discussed certain aspects that unit testing can improve within your team, such as development costs and the cost of manually testing your code. You’ll also learn about the types of tests and how you can benefit from automated testing.

What is Automated Testing?

Simply put, automated testing is the practice of writing code that is separate from the software being tested.

The main purpose of automated testing is to find broken parts of your application before it reaches production.

Does using automated tests mean you will release bug-free software? Of course not.

But automated testing helps find those bugs before the software is released. Let me give you an example of how automated testing works. Have a look at this block of code:

function calculateCostOfMilk(typeOfMilk) {   
   
   if (typeOfMilk === 'wholeMilk') return 3.05;  
   else if (typeOfMilk === 'skimMilk') return 1.40;   
   return 0.00;
}

Assume we have an application we just built and want to test it manually. The function above is a function that will get called after we fill a form with data and submit the form.

Imagine we have multiple forms in our application that are long and require different types of input. Manually launching the browser, filling in the different types of forms, and testing all of the components could take hours, if not days.

This increases production costs and eventually slows down the release and development of the application itself. With automated testing, we can write code that will fill in these forms and test our functions directly. Try this:

var result = calculateCostOfMilk('wholeMilk');
var result = calculateCostOfMilk('skimMilk');

This is easier than manually testing, and it only takes a fraction of a second.

Increased Cost

A lot of developers argue that development cost increases when using automated tests because you have to write the actual application itself and then turn around and write the test code for that application.

It does take more time to write the test, but it helps to mitigate the risk of releasing fragile code in the future and helps build a maintainable codebase.

I am not saying that automated testing will keep you from releasing bugs in your code — that is not true. But it does help you release a higher quality of code.

It’ll also help keep you from having to come back to the office at 3 a.m. when your boss is calling to tell you a critical part of the application is not working.

You’ll be wishing your friend had shared this article with you earlier.

It’s Cheaper in the Long Run

Some developers argue that manual testing is the best way to test applications because the costs are lower. These individuals argue what I like to call the cost-point argument.

You see, that is the reason most people give when they compare the amount of time it takes to complete something.

Spend time and money doing it the right way now so time and money are not wasted trying to do the right thing at the wrong time later.

With automated testing, you create a separate project for writing tests. In that project, you’ll write code and directly call the functions with different inputs and verify the functions return the right output.

As you can see, it does take more time to write the test for your application, but as your project scales and obtains more moving parts, you will eventually increase the cost and take more time to test your application if you are not using automation.

Tests With Benefits

The good thing about automated tests is they are reusable. You write them once and run them a million times.

Lots of teams find it beneficial to run their tests with every commit. With this approach, it makes sure breaking changes are caught way before a pull request is accepted into the master branch.

I personally like to give the team one command to run that does linting and testing in one go.

The devs know to run it before opening a pr because if there is a lint error or a test fails, the CI/CD system will flag the pull request and block it from being merged.

No breaking change in production is the goal.

With this approach, you can test all the execution paths in the functions of the app in a fraction of a second.

Writing automated tests also helps you write better code. When writing tests, you’re forced to think about the edge cases of every function in your application. You write tests for these functions, giving them various inputs and make sure they behave as you expect.

This will help you produce better-quality software with fewer defects. A lot of bugs in our applications are the result of unforeseen edge cases. One of your functions receives an input that you forgot to predict … and boom!

It blows up faster than my writing career!

With automated tests, you make sure that every function works with different inputs under varying circumstances, and those meddling bugs stay out of production.

Types of Tests

There are many different types of tests, but the three I am focusing on in this piece are:

  1. Unit
  2. Integration
  3. End-to-end

Remember, no one test fits all. You may use different types of tests depending on the type of application you’re building and the amount of coverage your team prefers.

We will go over these in a bit. For now, just know that there are three different types of tests that we can perform on the parts of an application.

Unit testing

Unit tests, a growing trend among software developers, determine whether certain sections of the code are acting as predicted under different circumstances.

In the context of single-page applications, unit testing is only going to focus on the component. If we have a failure in the template, then we’ll not know until runtime. Unit tests are fast and not as complex to write, but they don’t give us much predictability about the application.

In Angular terms, it tests certain components of the application without its template and many other external resources like file systems, databases, and API endpoints.

For example, in an Angular app, we have templates, services, and other pieces of our application that tie into our components.

A unit test would test just the components of our Angular app without touching templates, services, etc.

If your component does rely on a service, we will give it a fake instance of that service. Similarly, if your component relies on a router, you will give it a fake instance of that router.

In unit testing, we assume that the service and router are doing their jobs. So this allows us to focus on the component to ensure it’s working correctly. Let’s dive into some code to get a better understanding of how a unit test works.

export class VoteComponent {   
    totalVotes: number;  
     upVote() {   
        this.totalVotes++;  
     }
}

Above is our component, which is basically a simple TypeScript class. The totalVotes property will change every time the upVote() method is called.

Let's assume we have a button inside a template that calls the upVote() method like this:

{{ totalVotes }}<button (click)="upVote()">up</button>

When the button is clicked, we expect the upVote method to be called and the totalVotes property should increment by 1.

If the test notices different behavior, it’s flagged — and the developer can go fix it.

Integration test

Integration testing gives the ability to test a component with external resources.

Remember our VoteComponent? Integration tests have the ability to treat our VoteComponent as an Angular component.

To better understand this and since the integration test also tests external resources, we need to run it in an Angular environment.

Maybe there are certain build outcomes and environments you need to test the app in and expect a certain outcome — integration tests will handle it.

In this situation, we need to instruct Angular to compile our VoteComponent and its template together. So the test is aware of the two.

There is more test code to write since we have to run this in an Angular environment, but we’ll gain more confidence about the functionality of our component because the tests will run our app with the awareness of the template and component that compose the template.

Now, similar to unit testing, we’ll still provide a fake service to this component.

While integration tests are more reliable, they are still fragile because we are only testing a few parts of our application: the component and template.

This type of test doesn’t look at our application as a whole.

End-to-end test

This type of test will launch the application, test logins, fill out contact forms, etc.

This allows us to have more confidence in the software we release, but end-to-end tests are slow and fragile.

They are slow because of all the mechanics behind the tests themselves and the high percentage of code that is covered.

With the end-to-end test, we test the entire application as a whole.

It takes time for the test to run because it’s going to simulate a live user. They are fragile because one change to the HTML in a template could throw off the entire test.

For every change you make to the application, you have to adjust the test code works correctly.

End-to-end tests are only for key parts of the application. This is actually great in some scenarios.

Conclusion

Now that you understand the different types of tests, the pros and cons of them, when to use them, and how they work, you now have the basics to dive into learning one of the different ways to test.

No matter the type of testing you use, I promise you will build quality software and see fewer bugs in production.

Unit tests are easier to write, so I suggest starting there.

Just remember, no one test fits every scenario. There are situations where you would use one over the other.

Cheers!

Consider becoming a Medium member if you appreciate reading stories like this and want to help me as a writer. It cost $5 per month and gives you unlimited access to Medium. I’ll get a little commission if you sign up via my link.

Software Development
JavaScript
Programming
Technology
Web Development
Recommended from ReadMedium