This is the third post in the series about what we need to do better as AL developers, you can find the first two posts here:
Part 1: AL Developers we need to do better – Part 1 – Fredborg
Part 2: AL Developers we need to do better – Part 2 – Fredborg
In this post we are going to look at testing, now I know what you are thinking “oh no not testing” but we cannot get around the fact that to write better solutions we need testing, so what do we have to do to make software testing sexy, well I tried asking ChatGPT that question and this was its answer
Making Software Testing Sexy
Dennis Fredborg
How do we make software testing sound sexy
Software testing is an essential part of software development that helps ensure the quality and reliability of software applications. Here are a few suggestions to make it sound sexier:
– Emphasize the impact it has on delivering top-notch, user-friendly software to the market.
– Highlight the role it plays in identifying and fixing bugs before they become bigger problems for users.
– Call it a “quality assurance” process that helps ensure that software meets the highest standards.
– Emphasize the importance of testing in preventing potential security threats and protecting users’ data.
– Emphasize the creativity and problem-solving skills required in software testing, making it an exciting and challenging career.By emphasizing the positive outcomes and important role that software testing plays, it can become a more attractive and compelling field.
Well, I do not know if it sounds sexy, but it sure does highlight why we need to make testing part of any developer’s workflow, and if you are not convinced then there at plenty of examples of how wrong it can go if we do not perform prober software testing, one of these examples could be:
Ariane 5: Ariane 5 was a rocket with a value of $370 million that ended up having to self-destruct because, the software on the rocket had not been tested correctly, the error occurred because it tried to copy a 64-bit float value to a 16-bit integer variable which caused an overflow.
Therac-25: Therac-25 was a machine used to treat cancer patients with radiation treatment, but a software bug caused it to give patients too much radiation causing 3 deaths. The problem was not the bug itself, but more that the machine did not have good error messages, but had error codes like malfunction 54, but no one knew what these error messages meant and because this malfunction code was one of many, the technicians just pressed P and allowed the machine to continue. On top of this, the software did indeed have some fail-safe in the software, where if a value was not 0 the machine would not run, however, the variable that was used to store these checks was a 256-bit variable, and once it got above 256 the variable would default to 0, causing the machine to continue.
Now I know that most of us will never write software where bugs will have such a large impact as the examples above, however, it is not unheard of that we might introduce a bug that could result in our customers not being able to finish their shipments, so the customer cannot ship the items that they might have sold on their webshop, and the reason for this is that software development can be very complicated and we might not always consider all the factors, and unfortunately, there is no silver bullet to this problem, but what we can do is try to handle as many bugs as we can before we push our code to production. So let us see how we can do just that.
Not just unit testing
When most people talk about software testing, they automatically think about unit test, and while unit testing is an important part of software testing, there is so much more we have to look at. Software testing starts long before the first line of code has even been written, it starts in the planning phase, a good rule of thumb is that the earlier you catch a bug the easier it is to fix.
Catching bugs in the planning phase will help in removing roadblocks, and save time because it is easier to change something while you are still in the idea phase than it is once we start coding, and it will also save resources because we will not spend time on things that are not needed. Some of the ways that we can catch bugs in the planning phase are.
Requirements Gathering: During the requirements gathering phase, the product owner and development team should review the requirements and look for any potential design flaws or inconsistencies that could cause bugs later in the development process.
Threat Modeling: Threat modeling is a technique used to identify potential security threats in a software system. It can be used to identify potential bugs and vulnerabilities in the design before development begins. A good tool to use here would be the SWOT (Strengths, Weaknesses, Opportunities, and Threats)
Use Case Analysis: Use case analysis is a technique used to identify the functional requirements of a software system. By identifying the steps involved in each use case, the development team can identify potential bugs early in the planning phase.
The next phase is to write the user stories, here it is important that the user story is written in a way that all parties know what the expected end result is, it should be written from the perspective of the end user. It should be written in a way that is easily understandable and focused on the value that the feature will deliver. Additionally, it should be written from the perspective of the end user, making it easier for the development team to understand the requirements and build a solution that meets the user’s needs. Because if we know what the end goal is, it is also easier to write acceptance criteria for our user stories which later can be turned into unit test and flow tests in code. An example of a user story, with acceptance criteria could be;
User Story: As a sales manager, I want to be able to add a freight line to the posted sales document in Business Central, so that I can accurately reflect the cost of shipping for each sale.
Acceptance Criteria:
1. The ability to add a freight line to the posted sales document is added to Business Central.
2. The user can enter the amount of the freight charge on the sales order or invoice.
3. The freight charge is displayed on the posted document, along with the subtotal, tax, and total amounts.
4. The freight charge is included in the calculation of the total amount of the posted document.
5. The freight charge is recorded in the general ledger and is included in financial reporting.
6. The user has the ability to edit or remove the freight charge if necessary.
7. The changes made to the sales document do not affect other parts of the system, such as inventory management or customer billing.
Writing our user stories like this will not only ensure that we all agree on what the end result is, but it also makes it easier to perform manual testing during the test phase and write automated tests during the development phase.
Automated tests
Automated tests are a critical component of software development, and they help ensure that software is functioning correctly and consistently over time. Automated tests can take many forms, including unit tests, integration tests, and functional tests, but the common goal is to automate the testing process and reduce the amount of manual effort required to validate the software.
Some benefits of automated testing in software development include:
Improved reliability: Automated tests run consistently and quickly, helping to identify and prevent errors early in the development process. They should also be run in your build pipelines so that you test not only your new code but also that your code does not break existing features.
Increased efficiency: Automated tests save time and effort by eliminating manual testing, reducing the time it takes to validate changes to the software.
Faster feedback: Automated tests provide immediate feedback on the impact of changes to the software, helping developers quickly identify and fix any issues.
Improved code quality: Automated tests help to enforce coding standards and best practices, improving the overall quality of the software.
Better coverage: Automated tests can be designed to cover a wide range of scenarios, increasing the level of confidence in the software’s functionality.
The tests should be easy to maintain and update as the software evolves, and they should be run regularly to catch any regressions or errors that may arise. Additionally, it’s important to ensure that the test suite is comprehensive, covering all relevant scenarios and edge cases.
You can structure your test cases using the Given-When-Then structure.
“Given-When-Then” is a commonly used testing methodology that provides a structure for writing clear and concise test cases. It consists of three parts:
Given: This section describes the initial state or conditions under which the test will be run.
When: This section describes the action that the user takes, or the event that takes place.
Then: This section describes the expected outcome of the action or event.
By using the Given-When-Then methodology, test cases become more readable and easier to understand, helping to ensure that the tests accurately reflect the requirements and intended behavior of the software. Additionally, the structure helps to ensure that tests are well-organized and easy to maintain, reducing the risk of errors and improving the efficiency of the testing process.
One of the main problems when it comes to creating automated tests is that we do not structure our code so that it is easy to test, but writing code that is easy to test is an important aspect of software development, as it helps to ensure that the software is reliable and maintainable over time. Here are some guidelines for structuring code to make it easier to test:
Single Responsibility Principle: Make sure that each component or module in your code has a single, well-defined responsibility. This makes it easier to isolate and test individual parts of the code.
Dependency Injection: Minimize the use of tight coupling between components and instead use dependency injection to allow components to be tested in isolation. So rather many small functions that can call each other than one large one that does everything.
Code Refactoring: Regularly refactor your code to remove duplicated code, simplify complex logic, and make it easier to test.
Use Test-Driven Development: Write tests first, and then write the code to make the tests pass. This helps to ensure that the code is designed with testing in mind and that the tests accurately reflect the requirements of the software.
Keep it Simple: Avoid over-engineering and write simple, concise code that is easy to understand and test.
Avoid Global Variables and State: Avoid using global variables and states, as they can make it difficult to control the behavior of the code during testing.
By following these guidelines, you can structure your code in a way that makes it easier to test and validate, reducing the risk of errors and increasing the reliability of your software.
Now I am not going to write any unit tests in this post, because this post is already way too long.
I would recommend that you pick up the book Automated Testing in Microsoft Dynamics 365 Business Central by Luc van Vugt Search | Packt Subscription (packtpub.com)
Manual testing
Alongside the automated testing, you will also perform manual user tests, and the best way to do this is to have a testing framework in a place like Azure DevOps Test Plans that will help guide you through the test cases that the people involved with the project have agreed upon. Manual testing can be time-consuming and repetitive, but it is essential in ensuring the quality and functionality of the software. It can also uncover issues that automated testing may miss, as it allows testers to explore the software from a user’s perspective and identify usability issues.
Software testing is a science in itself, we have stuff like, white box testing, Grey box testing, Black box testing, smoke testing, load testing, performance testing, usability testing, and the list goes on, and I cannot cover all of these concepts in one blog post, I might take a deep dive into some of the concepts at a later point; in another series, but this series is more to bring some of the things that we as AL developers and consultants should know, and should at least take an active position on what we need to implement.
That was it for this post and this series, until next time stay safe.