DEV Community

Daniel Irvine 🏳️‍🌈
Daniel Irvine 🏳️‍🌈

Posted on • Updated on

Do devs really need to test?

In my last post I talked about ideas for convincing devs to do more testing. However, perhaps what I should have addressed is the topic of why do devs need to test at all?

In this post I’ll answer that question—and, just so you know, it’s not clear cut.

If software is your product

I’m a contract software developer who, like many other freelance developers, makes a career out of TDD, XP, quality, and so on.

For businesses like my own, for whom success is based entirely on the code they write, it makes total sense that they want to write the best code—for some definition of best—since if they didn’t they wouldn’t last long in such a competitive market.

Any time you read an article about refactoring, TDD, unit testing, anything to do with code quality, take a look at who the author is and what they do. Chances are they are a software consultant that’s really just selling their work. Either or that or they are very passionate, to an extreme level, about the code they write.

Throw it over the wall

Many devs have a “throw it over the wall” attitude to software testing. Meaning, let QA handle it.

In my very first job out of uni, I was hired into a company with a highly complex C++ Windows/MFC application. Since it was so complex, the grads weren’t allowed near it. Instead we were to spend the first year of our careers with the grand title of Software Engineer in Test, reporting to the head of QA.

It was this role that taught me how shockingly bad code can be.

It was also the first time I learned about the cost of fixing bugs depending on when you find them. The sooner you find a bug, the cheaper it is to fix.

Being in a QA team that found a lot of bugs, I knew that having QA find bugs was a serious waste of time and money for the business. The whole cycle of producing a build, QA testing it, finding a bug, writing a bug report, finding the developer responsible, communicating with them, having them fix it, all for the cycle to start again, takes a long time.

There’s a serious amount of process associated with QA and bug finding.

Now if the dev just does a little bit of testing before hand, they might find that bug and save all that hassle.

So this whole process taught me that the most cost-effective result for the business is if all bugs are caught before they make it over the wall.

(On the other hand, QA finding a bug is much better than a customer finding a bug.)

Better yet is if developers adopt working practices that avoid bugs in the first place.

Then QA can do exploratory testing, performance testing and all the other fun stuff, since they don’t have to worry about spotting our mistakes.

Newsflash: QAs are better at testing than devs are

There’s no replacement for a good quality tester. It’s so useful to have someone trying to break your code.

Unfortunately, having a QA team is a luxury that some businesses just don’t have access to.

So far, I count this as four reasons why you (as a developer) might want to test:

  1. Software is your product (you’re a consultant/contractor/freelance dev)
  2. You’re highly passionate about programming
  3. You’ve done a stint as a QA and you know how bad software can be
  4. You do not have access to a QA

What if you’ve answered “nope!” to all of those? Are there still any reasons to test?

There’s certainly one big one.

Tested code is simpler than untested code

I don’t have any facts to back this up, but the logic goes a little bit like this:

  • In order to test, your code must have a clean, accessible API
  • If you struggle to write a test, then you can think about re-designing whatever parts of the production code are giving you trouble
  • Tests that break often or need to be changed often is a symptom of poor code design, too. So once you have a test suite, continued use of it will start to pinpoint where the design of your system can be improved.
  • Untested code, on the other hand, can easily form into spaghetti code, which has a tendency to grow and eventually become a big problem, because spaghetti code eventually becomes too costly to maintain and build on top of it.

Let’s finish with the big reason why you wouldn’t want to test.

Ultimately, there’s no incentive for many developers to test

If you’re a permanent employee and your objectives are not based on testing, then why would you do it?

Many people will indeed having objectives of “fully tested solutions” but realistically, you’re getting paid to produce working software. If you produce buggy software that continually blows up in production then sure, you might have some questions to answer.

It’s relatively straightforward to produce working software without tests. Especially if you have a QA team to do that testing for you.

What would your future self want?

If you feel like you’re in this camp, then all I’d suggest is you think about your future career. Do you see yourself as a code champion? A thought leader? Someone who leads teams, someone who can work in all manner of environments? Then at some point you should consider getting good at testing. Even if it isn’t a necessary part of your job today.

Plus, I’m fairly confident your QA team will love you for it.

Discussion (16)

Collapse
jorgecc profile image
Jorge Castro

Tested code is simpler than untested code

Now, that is a bold statement.

For example, we have a webpage with a form that inserts information into the database.

What we could test?

  • The template? Well, good luck with that.
  • The action of "insert"? Then most developers fill the code with mockups that are not testing the real database but simply calling the function, adding a percentage to the test coverage and calling it the day.
  • The controller? (if any). How?
  • The validation of the information? It is the only operation that makes sense to test.

However, some developers want to test everything and poison the whole code with turnarounds, such as to "codify" the template.

Collapse
suckup_de profile image
Lars Moelleken • Edited

Hi, Acceptance-Tests is what you are looking for. :)

  • add some helper css-classes into your dom (test-, js-, ...)
  • and run the tests in headless-chrome in you CI server

e.g. via codeception.com/

<?php

final class UserTemplateAcceptanceCest {

    /**
     * @return array
     */
    protected function userTemplateProvider()
    {
        return [
            ['kunde_id' => 45127002, 'templateName' => 'Foo' . uniqid('Foo', true)],
            ['kunde_id' => 45127003, 'templateName' => ''],
            ['kunde_id' => -1, 'templateName' => 0],
            ['kunde_id' => 0, 'templateName' => 'FooBar' . uniqid('Foo', true)],
        ];
    }

    /**
     * @dataProvider userTemplateProvider
     *
     * @param \AcceptanceTester    $I
     * @param \Codeception\Example $userTemplateData
     *
     * @return void
     */
    public function testCreateTemplate(\AcceptanceTester $I, \Codeception\Example $userTemplateData): void
    {
        $I->wantTo('Create new user-template.');
        $I->amOnUrl($I, UserTemplateDetailsView::getUrl(['element_id' => 'new']));

        $I->waitForElementVisible('.test-PageTitle');

        $I->fillField(['name' => 'templatename'], $userTemplateData['templateName']);
        $I->selectOption('kunde_id', ['value' => $userTemplateData['kunde_id']]);
        // ...
        $I->clickWithLeftButton('.test-HtmlFormExtendedSubmitButton');

        $I->canSee($userTemplateData['templateName'], '.test-HtmlTableContent');
    }

    /**
     * @depends      testCreateTemplate
     *
     * @dataProvider userTemplateProvider
     *
     * @param \AcceptanceTester    $I
     * @param \Codeception\Example $userTemplateData
     *
     * @return void
     */
    public function testDeleteTemplate(\AcceptanceTester $I, \Codeception\Example $userTemplateData): void
    {
        $I->wantTo('Delete created User-Template.');

        $I->waitForElementVisible('.test-PageTitle');

        $I->fillField(['name' => 'usertemplate_id'], $userTemplateData['templateName']);
        $I->clickWithLeftButton('.test-ButtonIconSearch');
        $I->waitForAjaxWithSpinner();

        $I->clickWithLeftButton('.test-SelectAllElements');
        $I->clickWithLeftButton('test-Act' . StammdatenUserTemplateListChangeListDeleteAct::class);

        $I->clickWithLeftButton('.test-ButtonExecute');
        $I->acceptPopup();

        $I->cantSee($userTemplateData['templateName'], '.test-HtmlTableContent');
    }

}
Collapse
d_ir profile image
Daniel Irvine 🏳️‍🌈 Author

Thanks for picking me up on this 🤣 I don’t disagree with you. Deciding what to test and at what level is one of the hurdles that trips people up. Overtesting is a serious problem. For unit tests I usually avoid testing anything ”static” like HTML or CSS. Those are tests that I’d rather leave to QA, or write up as system/acceptance tests in some other way.

To come back to my statement... yeah, there’s a huge assumption hidden within it, I‘ll see if I can find a way to make that clearer, as discussing how to test well is waaaay beyond the scope of this post 🤗

Collapse
aleksikauppila profile image
Aleksi Kauppila

Overtesting is a serious problem

Does this really exist? I would be interested in hearing some examples. 🙏

I can definitely see a problem in time spent in testing. And that is most likely spent in manual testing because of not having knowledge on how, on what level and what exactly to test.

Thanks for a great post! 🍻

Thread Thread
d_ir profile image
Daniel Irvine 🏳️‍🌈 Author

It might be something I’ve just dreamed up, or maybe there’s a better name for it, but here’s how I think of overtesting.

Overtesting is what happens when your write tests that cover more surface area than necessary. One way this happens is relying on end-to-end tests instead of unit tests. Greater surface area means more chance for tests to break when code is changed. In other words, you get brittle tests.

Hopefully that makes sense?

Thread Thread
jessekphillips profile image
Jesse Phillips

Each test is additional code which must be maintained. If the tests need to be updated with every code change, even though the functionality they are expecting to test isn't changing, it becomes a liability.

Clearly that isn't because there are too many tests, but it kind of is. The mantality this come from is that every test is valuable. While you could write another test, clearly this is covering more and may find an issue it just isn't this time.

Thread Thread
aleksikauppila profile image
Aleksi Kauppila

It makes!

I think this is due to focusing the tests on the wrong level.

Too small or inappropriate details are verified in a test that is done by eg. Calling the service over HTTP.

Collapse
evgeniir profile image
Evgeniy • Edited

End-to-end test for success path if there`s no complex logic.

Separate QA for checking that code works is anchor that slows down processes.

Tested code is simpler than untested code

Now, that is a bold statement.

Statement above is about unit-tests.

Collapse
axelledrouge profile image
AxelleDRouge

Thanks I quite agree with you.
In my current job, I often am the only dev front-end, with no QA (what's this ?? not sure that my manager even know the term) so I have learned to appreciate a lot TDD and testing.
But while I am getting better at unit testing, I still have a lot of difficulties understanding the methodologies, like how to correctly use mocks, or the functional and e2e tests. It really is a whole part of the job, I just don't have the time and ressources currently to learn it (and of course, no one to learn it from) so I am sticking to unit testing, for the moment, until I can learn more.
If someone has good ressources on the subject, I would thank you for it

Collapse
d_ir profile image
Daniel Irvine 🏳️‍🌈 Author

The best way to learn (IMHO) is to work with others who REALLY know how to do it. I had been doing what I thought was TDD for 5 years before I joined a TDD consultancy. I was lucky to have colleagues who helped me improve. So if you get the opportunity to pair with experienced TDDists then I suggest you take it. You’ll learn so much. One way may be to join a local coding dojo meetup or software crafter meetup if you can find one (see softwarecrafters.org).

Since you’re a front-end dev, you might also be interested in my book, Mastering React Test-Driven Development. It covers unit testing and also acceptance testing with Cucumber and Puppeteer.

Collapse
axelledrouge profile image
AxelleDRouge

Thanks a lot :)
I probably will buy your book (today, before Brexit XD) It seems exactly what I need thanks. At it probably will help in my company

Collapse
wolfhoundjesse profile image
Jesse M. Holmes

Newsflash: QAs are better at testing than devs are

This. Our QA often thinks of scenarios I would miss. She's the heroine of this story.

Collapse
theodesp profile image
Theofanis Despoudis

Does that imply that we should offload all of our testing effort to QA's? No

Collapse
wolfhoundjesse profile image
Jesse M. Holmes

Yes, please don't dump your buggy code onto QA because you think it's their job to find problems. What I was trying to say is that I learn new things to look for every time QA finds something.

Collapse
prahladmishra profile image
Prahlad Mishra

Agree with you, but getting it to the habit of other team members is a long shot. I am trying to guide by example and hoping some day unit tests with high coverage would be the requirement instead of optional.

Collapse
codemouse92 profile image
Jason C. McDonald

We require tests as part of revisions (think Pull Requests) in our company workflow, and they're reviewed as part of the code accordingly. If you don't know how to write good tests, learn how. ;)