El Kapitan Obviouso’s thoughts on Testing Software

software-testing

For some reason I’m writing a bunch of blog posts on what I’d consider to be kinda basic stuff at the moment. It’s not like there aren’t already a thousand blog posts out there on this exact topic. como tomar ivexterm niños Anyway, for what it’s worth… let’s proceed.

Why do we test software?

To see if it works. Turns out writing software is not easy, you write one thing and the machine goes off and does another. Sometimes something mundane but annoying like crashing, sometimes something exciting like killing people. So we like to confirm that our software works before we ship it out the door.

Problem 1: Software is complex. Even a basic website backend these days would usually handle user logins, accept user input, query a database and have a fancy responsive user interface front end that displays nicely on anything from a phone to a PC. Because software is so complex testing it is also complex. There are literally thousands of states that the program can be in at any given time. Thousands of ways to break your lovely code in other words.

Problem 2: Software changes – it is not static. User requirements change. Management makes decrees from on high. An API that you depend on changes. Tricky programming problems and bugs require workarounds and hacks. Your beautiful code begins to look frayed at the edges.

Problem 3: Bugs are consequential. Not only are there nefarious scheming hackers out there who’re keen to slime their way into your application and steal stuff like your users’ names, addresses and late-night shopping habits, but your own mistakes can blow up in your face. resdue ivermectin in cattle A wrong financial calculation or incorrect security protocol can literally doom your company. I ain’t even joking. Look up Knight Capital for a tale to frighten young coders at bedtime. And they’re only one of thousands.

The net effect of these problems is that whenever one deploys software it needs to undergo testing first. Sometimes you can get away with shortcuts, but the choirboy answer for this stuff is that you gotta run a full test suite before deploying. Even then, testing is a bit of a wing and a prayer situation. You will get production bugs no matter how good your testing is and also no matter how good your management processes or your coders are.

How do we test software?

There are generally two ways to test software:

  1. Human testers
  2. Automated testing

Whichever way you do it, you need a list of test cases, which are basically specifications of what the software is expected to do given a certain state and certain inputs. At each release of the software the tester – human or automated – verifies that each of the test cases passes.

With human testers you can also do unscripted testing – meaning they just fiddle with the software like a normal user would and see if they can break it and if so how much.

Advantages of human testers:

  • There’s no one so unpredictable as an actual user of your software. No one who’s gonna go and do something they’re not supposed to like press the big red button marked “Do NOT Press” (although, if you have one of those you need to have a serious talk with your designer).
  • Human testers test the software as it will actually be used.
  • They can easily do things like “Click on the Button” which can be a real pain to script into automatic tests.
  • They are independent of the developer of the code. This is important because as a developer you can easily get so close to the problem that you assume that a user will do things in a certain way or understand something that you think is obvious.

Disadvantages of human testers:

  • You have to pay them.
  • They get bored. So would anyone.
  • They can miss things.

Advantages of automated testing:

  • You can write an automated test suite that runs every time you build the code.
  • They are repeatable for free and can generate nice reports with green dots and statistics.
  • As long as there’s a test case covering a particular condition, it will always be tested, meaning that if you make a change and it accidentally breaks that functionality, you’ll know.
  • A set of well-written test cases can be taken as documentation of how the code is supposed to work.

Disadvantages of automated testing

  • Effective tests are typically difficult to write and doing so is a skill which not everyone has, although everyone thinks they do.
  • You have to script them – you can’t just give the automated testing engine the software and tell it to try and break it.
  • Bad automated tests are (in my opinion) worse than no tests at all.
  • Certain code metrics like automated test code coverage are easily measured and can become fixated on by coders and management alike as proxy measures for code quality, which they are not.

What kind of tests can we do?

Probably the easiest tests to understand are Acceptance tests. These are the tests that you define based on the program doing what it’s supposed to do. For example, if you have a program that’s supposed to sort a list of strings into order, then an acceptance test for that program is to give it a jumbled list of strings and see if it manages to correctly sort them. Acceptance tests confirm that the software is fit for purpose. They are high level tests that confirm that the entire system works as designed.

Here’s an immediate problem you may see with the previous example. Our program must take any list of strings and sort it into order but we’re only testing one or a few lists. This is an inherent problem with any type of testing. The system is designed to work in a general case, but we can only do specific tests. You can’t get away from this. It’s the nature of the beast. There are a couple of things you can do to mitigate this though. First, you can test specific edge cases that you suspect might give you trouble. Second, you can test random cases that are representative of the sort of “average sample” of input data you might be dealing with. An example of an edge case would be an input list of strings sorted into reverse lexicographic order, with the expected output being that they will be sorted into standard order.

Another easy to understand type of testing is Regression Testing. Regression tests are written in response to bug reports. pastillas veridex ivermectina Once you’ve fixed the bug you add a regression test to your test cases to make sure it doesn’t come back, because software being what it is, it absolutely can come back. Someone messes up a merge, or some library that you depend on reverts a fix of their own… It happens. Regression tests check that known bugs are still fixed.

You can do both regression and acceptance testing with human testers – sometimes the bug or feature is complex enough that it is the only way to do this kind of testing – but there are many frameworks which attempt to make scripting automated acceptance and regression tests possible. Another thing to notice is that Acceptance and Regression testing applies to the system as a whole.

There are two further types of automated tests that we can do that are closely related. Unit Testing is where instead of writing tests that apply to the system as a whole you write tests that apply to only a specific unit of the software, usually at a class or function level. Integration Testing is when you take a small bunch of software units and verify that they interact correctly. Note that these kind of tests do not verify that the software as a whole works as designed, they just confirm that individual moving parts and assemblies of moving parts work “properly”. Unit and Integration testing generally applies to subsystems of the system and not the system as a whole.

An example

Let’s consider a car factory – for some reason programmers always talk about car factories. We’re designing a new kind of car, the not at all alarmingly named Explodey 3000, and we’re gonna take it to production. Because we like dollars and dislike lawsuits, we are going to test our new cars before we release them to the general public.

Unit testing would be that we’d test the individual engine parts (units) separately before integrating them into the engine. Integration testing might be testing whole systems (engine, electronics, braking) of the car individually – these are not the whole car, so it’s not acceptance testing, but they’re at a higher level than the individual unit.

Acceptance testing for our new car design will consist of a proper road test. We will get qualified test drivers into our test track facility, bang them into our prototype vehicle and check that they can steer it properly, the accelerator works correctly and so forth. For the first few prototypes we’ll also rather just stick a test dummy in the car and make sure that the thing doesn’t just drive straight into a wall when we fire it up.

Regression testing would be for example if we noticed that there were problems with the braking system, that we would be extra careful once we’d fixed those problems that with each new prototype the braking system gets fully tested.

Test environments

When you deploy software, you typically deploy to an environment. The production environment is where your software is out in the world and your customers can use it. But typically you don’t want to do testing in production. You want to only deploy tested software to production. Ideally you want to catch bugs before production because bugs in production result in unhappy customers. So usually we deploy to a test environment before we go to full production. We run all our tests – human or automated – in the test environment and once they pass we deploy to production. You can have multiple test environments depending on many factors such as the size of your project, the project management method and how you handle deployments.

An environment is anything that recreates the operating conditions of your software. For example if you are deploying a web application which uses a SQL server database connected to a Java Spring Boot backend application which talks to an Angular front end, you have one set of all those things which is used by all your customers, and you create another deployed SQL server / Spring Boot / Angular combination which is as close as you can get to identical to your production environment, which you can then use for testing.

If on the other hand you are deploying a Windows Desktop application (unusual these days but they do exist), then your production environment is all of your users’ machines (ugh, disgusting) and your test environment is your own Windows machine. Windows comes in a million flavours and so do the hardware/software configurations of your users’ machines, so good luck figuring out why their particular bug cropped up.

Conclusion

There is NOOOOOOOOOOOOOO conclusion. There may be a part 2.

About the Author

I’ve got some experience writing code. I run quite a lot. The last book I read was about Gavrilo Princip. There’s about to be a thunderstorm here. Here is Johannesburg, South Africa. There is another Johannesburg in the USA. I know how to make chocolate sauce.