I have seen once such a meme: “If debugging serves to remove errors from the code, programming certainly involves inserting bugs into the code.” There is some truth in it. Modern IT systems implement a lot of very complex processes, it is very easy to make a mistake. The programmer creates a tool that can be used in different cases. Testers and then end users will apply this tool in a way that the author hadn’t even imagined before. Combining this with ordinary human error during software development creates a mix that sooner or later will always “explode”.
So how should a programmer work so that the effects of his work are not negatively assessed after just a few clicks? Does the programmer have a chance to avoid simple mistakes? I have been creating a business application for companies and institutions for over 15 years. Over the years, I have developed a pattern that allows me to discover many simple errors at an early stage. This is a set of simple tests that significantly increases the quality of the produced software. Applied together with automatic tests (from unit to integration) they give a chance to eliminate many mistakes.
Most consumer applications can be generalized according to the following scheme:
No matter if we create a module of invoices, complaints, orders, reports, users, we can more or less always find the above pattern.
The first problem that appears during simple tests performed by the programmer is the approach to the pattern of permissions. The programmer will perform the test using the role with the highest permission. In this way, I want to check if all components are working properly. It is a mistake to stop at such testing. Majority of future users will operate on the minimum permission required. It is worth enriching the basic check of the new functionality with the lowest possible permission to perform a given operation. Such a test allows to:
A perceptive reader will probably immediately think about the roles of users who can do more than the lowest role, but are not administrators. Should the programmer check all possible cases? Yes, because he or she should verify if the settings work for other roles or claims. No, because he or she does not have to log into the system thoroughly for every possible type of user verifying the operation. What about the other cases? Cold calculation of the code and delegation the functionality to a tester allow to eliminate most errors in this area.
The ability to create new and to edit existing elements is the basic functionality of each module. By performing the following simple tests many different cases of application can be verified. When testing a user form (or dedicated API) for creating or editing, it is worth following the path below:
It should be a good practice to verify such operations as: saving, modifying or deleting directly on the database. When verifying the record, it is worth verifying that the data is being written to the appropriate columns and whether they are read and displayed correctly. This is to eliminate mistakes in the style of saving the net amount in the place for the gross amount and vice versa.
In the above method it is not possible to check all test cases, but it is possible to check if all the applied mechanisms work. At the testing stage, we should receive the answer whether these mechanisms are working properly.
Another very common element to check is the list of elements, the table. Very often it will be a view from which you go to the edit form. Here you can again talk about a simple list of tests that allow for an initial assessment of the programmer’s work effect:
At this stage, it is also worth checking if there is a mistake regarding the assignment of data to the appropriate columns in the appropriate format — here it is very easy to make a mistake.
All types of printouts, reports, statements are very difficult to test and verify. It is necessary to prepare a set of test data and maintain it at a level adequate to the current state of application development. This will keep the data source in a state that allows you to verify, for example, invoice printout or a sales report over a given period. How to construct such a set of test data:
Because work on e.g. the invoice module can be significantly extended in time, it is also worth updating the status of your own test data set with subsequent system updates. Contrary to appearances, this allows you to significantly save time by being constantly ready for testing.
After preparing the script or package updating the database and running it on the development machine, I strongly recommend that you should do this test also on the test machine. Configuration or server versions may differ between the development environment and the server. Verification of changes is a must.
We are happy to use conditional compilation. It allows, for example, to write code that will perform the required task step by step — just in time for the needs of the debugger. This carries the risk of not adapting the code changes to the Release version. Therefore, checking tests should be done in Release mode. Surprisingly, you can do such tests on the programmer’s computer.
Modern systems are very complex and carry out very complex tasks. However, they can be systematized into fragments that can be described as successive CRUD elements. By using the presented set of simple tests you can eliminate many errors. In addition, by testing at a low level of permissions in a production-close environment, you can avoid many unpleasant surprises. I encourage you to create your own list of steps to verify the new code.
Written by Paweł Szymura
Senior developer and technical leader at Evertop. Coding since 10 years old.
Personally, photographer and squash player.