Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I know that a writing test case is one of the way to do some programming level testing, but how to test some careless mistake? or how to reduce? For example, a buttonA, should perform ActionA, but sometime, just human mistake, the buttonA perform ActionB. And it requires the human test, it seems can't automatic the testing process, any hints to do so? Thanks.

share|improve this question

closed as too broad by gnat, Corbin March, Dan Pichelman, MichaelT, GlenH7 Sep 12 '13 at 2:57

There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs.If this question can be reworded to fit the rules in the help center, please edit the question.

Try automated UI testing: – Matthew Flynn May 28 '12 at 3:23
How to reduce careless mistakes? Well the obvious answer... "be less careless". – LachlanB May 28 '12 at 3:53
@LachlanB : This approach is an unreliable way to reduce software defect density, and is known not to scale well. – mattnz May 28 '12 at 5:09
up vote 5 down vote accepted

Efficient testing of your program code really comes down to how you focus your testing efforts. Sure, I could recommend lots of different tools and systems to help you run your tests, but carelessness can't be caught very easily unless you have some means to determine what levels of carelessness you are willing to test, and how much effort you are willing to spend on it.

The simplest approach that I can think of is really to focus on writing your test cases up front, based on the requirements specification. This test first approach is most commonly used while practicing the Test-Driven or Behaviour-Driven methodologies. Why do I call this the simplest approach?

If you write tests after the code is already implemented, you cannot be certain that something silly hasn't already been done in your implementation code, and every test you write after the fact to catch all of the edge cases that you can think of won't necessarily zero in on the sorts of problems you are probably most hoping to avoid. While the up-front testing effort is minimal, the post implementation debugging effort is likely to be extended, and more focused on chasing the problems that your testing was unable to catch. This is because when you write your implementation code, your mind is more focused on solving the problem at hand, and less focused on how testing and edge cases will be dealt with afterwards. Testing after the fact can become quite complicated, particularly if you need to change your code to accommodate your need to provide tests, and even more so if you start to break things in your effort to better test them.

When you write your test cases first, you are effectively changing the way you look at your code. By writing the test before the implementation, you are basically focusing how you will later implement a feature based on your understanding of the requirement, and how that requirement will be validated. It's a very profound focal change which essentially keeps your efforts narrowed down to the feature you are implementing without the distractions that other features often bring, and you also achieve three very important things. The first is that you end up writing implementation code to the specification only, and by this I mean it encourages you to resist the urge to gold-plate your code with stuff that the customer hasn't necessarily asked for. The second is that you should already have all of the testing requirements covered so that you will know when the implementation is essentially complete when all of you tests pass. The third and possibly most important achievement is that when it comes time to modify your code, you will know if your modifications are wrong if they break any of your tests, but that's okay too, as you will know when you have fixed things when your tests pass again, and this gives you the confidence to make whatever improvements you feel will be necessary to your implementation without breaking the functionality determined by the specifications.

So how does this answer the OP's question? Simply that by keeping the efforts focused on the specifications, you are already writing software in a more efficient manner, and if your tests are providing you with the backbone for your implementation effort, you will be reducing the amount of time you spend providing tests that offer little additional value to your project, while using your time more efficiently to test those elements that bear directly on the specifications themselves. Will this catch problems where actions trigger the wrong events as the OP describes? If your tests focus on validating the behaviour of your specified features, then it most probably will catch many of the more obvious 'human-error' types of bugs such as the OP described, however test-first is certainly no panacea. You will always need to be diligent in how you create tests for your software, however the ability to move forward rapidly with the support of tests already in place will certainly provide you with an opportunity to achieve a greater overall efficiency, without resorting to "heroic" post implementation testing efforts when your project is running late and you might otherwise be tempted to skip the testing simply to meet your deadlines.

share|improve this answer

Maybe a better question would be: Why do unit tests work at all? I mean, if you look at it, then you're writing a program B to check program A. Why should B be better than A?

There are various factors which contribute to the success of unit tests:

  1. Unit tests are more simple. Code in A is often complex so it has more bugs then the simple unit tests.
  2. You always make the same mistakes which means you get some things always right. There is no need to test the things that you're doing right all the time. So you don't need unit tests for all the code in A. Less code -> less bugs.
  3. When a bug report comes in, you can write a unit test for this specific case which makes sure that this bug never, ever happens again. This gives you a lower limit for the quality of your code. The quality of all the tested code can never sink below this limit.
  4. Write only the unit tests that you need. It's fun to write unit tests until you get 100% code coverage but the effort spent on the last 20% coverage will cost your four times as much as getting to 80% coverage. Usually, it's wasted effort (see also point #2).
  5. It helps you stay focused. When something is covered by a unit test, you can forget about it - a never-bored computer will make sure it works and stays working without any effort on your side. If you test manually, you'll eventually stop testing some things because they work too often and you get bored.

This gives you some hints on a good testing strategy:

  1. Learn which mistakes you make. Classify them. Don't try to avoid them on principle - you'll be wasting effort. Instead, focus on the most dangerous mistakes and ignore the petty ones. Making many typos? Get a spell checker or a English language student. A good source for this kind of information is your bug tracker.
  2. Test until you get bored writing tests. If you start asking yourself "Do I really have to write another test for this?" stop.
  3. Write more tests when you find a bug. They often come in herds. And the tests will help restore your confidence in your work.
  4. Write tests for code that isn't covered.
  5. Write tests for code that you don't understand.
  6. Write tests before you fix a bug. That way, the bug will stay fixed.
  7. Be careful when to throw away tests but never afraid.
  8. Write one test per requirement. If possible, keep those in a suite. That way, you can tell any time how many requirements you have already implemented.
share|improve this answer
There is a very good reason to "test the things that you're doing right all the time." Someone else modifying the code (or a dependency) may break it and needs to know that he or she hasn't done so. – Matthew Flynn May 28 '12 at 18:22
If someone else modifies a piece of code, they need to write the necessary tests, too. Asking me to write tests for an unknown, future developer doesn't make much sense. Also there is no way to avoid every bug/mistake. Relax. As long as most of the code is healthy, you will always have the time to fix unexpected problems and learn from them. – Aaron Digulla May 28 '12 at 20:20
+1 from me. As regards your first point 4 however, I feel the need to cheekily respond with "lies, damned lies & statistics". By that I mean that the Pareto Principle is often misapplied in software and doesn't always hold true, particularly when using BDD/TDD where you can get 100% test coverage with relatively little effort. That isn't to say however that 100% of tests will necessarily cover every type of failure if either the tests are too complex or the implementation isn't very lean. If 80/20 were true, we'd need only do 20% of the work ;) – S.Robins May 28 '12 at 23:48
The test is to show that a given desired functionality is achieved by the unit in question. If someone modifies the code (or something the code depends on) to support a different desired functionality, that doesn't necessarily invalidate your requirement. If it breaks yours, you've got problems. This is called REGRESSION TESTING and it's really really important. – Matthew Flynn May 29 '12 at 0:05

Every test requires a human, automated or not. If you are going to write unit tests, you at least have to invent and code each test once. That is a manual process, where you have to make sure you are testing the right things.

Same is true for testing the behaviour of UI (for example, to see if buttonA really does ActionA). Someone has to press the button, at least once, and observe what happens. There are also tools which can help you to automate that process on the GUI level. (Remark: I have never seen a GUI level testing tool which was worth the effort to be introduced into my projects, but that may be different in other projects).

share|improve this answer

You can create a list of inputs of possible human interaction with the software. This can be a button press, a text change whatever..

You can then match each of these inputs with an action to be performed. This creates an equal sized list of actions to be performed.

And you can then fire the events in the first list and check that each event fired calls the mathcing action in the second list.

This creates a formal definition of set of user interface interactions that your application has. It still needs to be written by a human being but reduces some trivial mistakes.

Especially if your actions are embedded in some kind of UI specific code like XML or XAML these mistakes occur more.

GUI testing can be automated too, but that costs too much for most of the software projects. Take a look at Wikipedia.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.