Everything CF Summit 2018: ColdFusion & Unit Testing, BDD, and Mocking using TestBox & MockBox
In the Spring of 2015, a software glitch was discovered that may have had the most grave of consequence. The bug was detected in the target detection software of the United States Air Force’s F-35 Joint Strike Fighter function. When flying in formation, the jets were unable to correctly identify missile targets. The planes could not differentiate between a single or multiple targets. This caused one news agency to report that the warfighters were seeing double. This mistake ended up costing millions of taxpayer dollars and precious man-hours.
The entire situation could have been avoided with one simple software fundamental. Testing. Failing to perform testing on your CFML project may not be as consequential as the F-35’s situation. But it may have negative connotations for your project or your company. By taking a look at the fundamentals of testing for your ColdFusion projects, we can see just how vital it is.
What You Need to Know as CIO
Let’s get down to brass tacks here. Why is knowledge of testing, development strategies, and automation tools important? Failure to do proper testing can lead to many more post-deployment bugs which can hurt your company’s bottom line. The costs for extensive rework greatly surpasses the time it takes to do things right the first time. It is always better to do a little predeployment preventative maintenance than post-production repair. It’s that simple. Understanding how testing and development strategies work are integral to making that happen. Next, automation tools are a godsend. They help your development team achieve maximum efficiency for their testing and mocking phases. Don’t waste valuable company resources testing and mocking manually when it can easily be accomplished via automation.
Unit testing is defined as a method of software testing. It is done through which individual units of data are tested to determine whether or not it is fit for use. A unit is defined as the smallest piece of functionality which can be tested in isolation. Different types of Data Units which can be tested include:
- Source Code
- Usage Procedures
- Operating Procedures
- Program Modules and Associated Data Sets
There are many great advantages for performing Unit Testing.
The first of these is finding your problems early. There are few things more frustrating than finding lots of bugs and problems in your code — especially after deployment. Unit testing can help alleviate those frustrations. By running tests, problems are more likely to be found earlier in the development process. You can avoid spending extra time and resources to repair problems if you catch them in the first place. Also, poorly written code can be very difficult if not impossible to test. Unit testing eliminates this problem. By unit testing early, you can readily find poorly written code prior to having an error pass by undetected. This is done with broad scale testing methods. Not only can you find problems early, you can easily pinpoint their exact location with unit testing. Examining small pieces at a time works similar to a GPS system. You will be able to see exact “coordinates” to your problem areas. This makes solving potential disasters much easier.
Unit testing also simplifies integration of code. Uma Ghotikar suggested writing the test for the smallest piece of code possible when performing unit testing. She does this for a very practical reason. If that minute piece of code passes its testing, it can be easily reused without further testing. That is because it has been previously verified. This can help tremendously with integrating your code and expediting the code writing process. Unit testing also helps to facilitate changes to your code and overall project. If the code changes, it will be easier to locate what else needs to be altered. This will provide a proper operation for your code.
Another great advantage is the speed at which unit testing may be conducted.
Unit tests are exponentially faster than general testing due to the relatively simplicity of the tests. Along with, it is very easy to allow for automation of these tests for your CFML project by using tools such as TestBox and CF Selenium. Not only does the speed of testing become more efficient, but so does the area of coverage. All parts of your code is thoroughly combed through to provide you with the most accurate findings. When using automated testing, this is often shown as a full report after completion showing problems and their severity levels.
Another great advantage occurs when you write your unit tests before you code. This can allow you to define where your code needs to raise an error. However, when writing unit tests there are some recommended guidelines you follow to ensure your best testing experience:
- Unit tests need to be written to provide fast, immediate feedback. The amount of time wasted waiting for results when testing large programming and coding would be monumental if immediate feedback is not given.
- Avoid database, file system, HTTP, and API calls. Mock them instead using a mocking platform such as MockBox.
- Get modular. Unit tests should be modular to allow for reuse of the code. Create the smallest unit tests possible. Writing a single use piece of code again and again wastes time and resources doing something that should not have to be done.
- Tests should be independent of other units and tests. This allows for the best accuracy possible when performing testing.
- Be sure to define clear purposes for your test. They should only test one functionality.
- Do a fail-safe test. This means to verify your code can fail before writing it to pass. You want to make sure that your test works properly and catches errors. This ensures you do not have errors sneak by your testing because your test was developed incorrectly.
- Tests should be robust. They should produce the same results under any given circumstance.
- Keep your tests up to date. If you change your code, be sure to change your tests accordingly.
- Define your expected outcomes of the test. You should not be surprised in how your test will respond.
Most modern ColdFusion apps are written in a Model View Controller (MVC) style. Unit testing primarily tests the model portion of your app — albeit Controller testing can be performed as well. Remember, unit testing is only one part of testing. Other types of testing should be performed also to ensure the best version of your app as possible.
Unit testing is very closely associated with TDD (Testing Driven Development). TDD states that testing should be created prior to the writing of any code. By doing this, your end result is dictated by your code. You write code that fulfills your tests in order to achieve end production. TDD normally occurs in a five step process.
- Specification- This is where you actually write the test.
- Red- Perform the test to verify that it fails.
- Write your production code. Keep this to the minimum amount needed to perform desired function (In ColdFusion, this is often referred to as the CFC level.) and pass the test.
- Green- Run your test until it passes.
This process can be commonly referred to as Red-Green-Refactor. These tests are written from the viewpoint of the developer. As stated above though, there are many different types of testing.
Related: 077 Fundamentals of Unit Testing, BDD and Mocking (using TestBox and MockBox) with Uma Ghotikar
BDD (Behavior Driven Development)
Unit testing and TDD are considered as more of a low-level approach. BDD is a much broader form of testing development. It is the more agile and user-focused approach. BDD is not so much a different form of development but more of an evolution of TDD. BDD tests are centered towards a system’s behavior. With this style, you create features that create scenarios which test behaviors your application is supposed to have.
Uma Ghotikar breaks down BDD with a very simple example. If a customer fills out a form on a website and hits submit, the expected response behavior is a verification notice. Now, a series of questions needs to be asked.
- Did the user fill out the form? Check.
- Did the user hit submit? Check.
- Was a response generated? Check.
- Was the response delivered properly to the user?
This signifies the behavior your system should have. The response should be properly sent went a user acts upon it. By developing to user behavior, you can make sure you have the proper outcome desired.
Using BDD tactics has many advantages but there are some essential things that need to be in place before you can start.
- Requirements should be turned into user stories that give definite examples.
- Each example needs to be a valid user scenario.
- You should have an understanding of the “given-when-then” formula and the “role-feature reason” matrix.
- You should have the awareness to write towards behavior specifications vice unit testing.
So, what are the “Given-When-Then” formula and “Role-Feature-Reason” matrix?
The Given-When-Then formula is a very simple template used when creating BDD tests.
Definition Example Given A certain scenario The user has not submitted form information. When An action takes place The user presses the submit button. Then This should be the outcome Proper validation messages are shown.
The Role-Feature-Reason matrix is used to help in the creation of user stories.
- As a (Role)
- I want (Feature)
- So that (Reason)
Example: As a ColdFusion developer, I want free Containerization software so that I can better scale my CFML projects.
Once you have defined your BDD essentials, you can start to experience the advantages offered from BDD.
- This is a much faster form of development compared to TDD — which can become tedious at points.
- Since BDD uses simple language, it can be implemented on a much easier learning curve.
- It promotes much better communication between developers, testers, and owners.
- It can be spread to a much wider audience due to it not being a technical form of development.
54% of ColdFusion developers still do not use any testing and mocking frameworks. This percentage is almost the same as last year’s. When will they get the message that taking time to automate testing cuts down on time debugging later? Thankfully, there are a number of automation tools that we can use to help with developing our CFML projects. TestBox from Ortus Solutions is one of these tools. It comes with a testing framework, runner, and assertion and expectations library. TestBox takes your testing and development to a whole new level. Based on BDD principles, it allows for clean obvious syntax when testing your ColdFusion projects. Along with BDD, TestBox supports MX style and xUnit style testing more associated with TDD. According to Ortus Solutions, TestBox is capable of many more functions than just BDD and TDD style testing. These capabilities include:
- Testing life-cycle methods
- MockBox integration for mocking and stubbing
- Ability to extend and create custom test runners
- Ability to extend and create custom test reporters
- Extensible reporters, bundled with tons of them:
- JUnit 4 XML
- Text (80’s style)
- TAP (Test Anything Protocol)
- Simple HTML
- Min — Minimalistic Heaven
- Asynchronous testing
- Multi-suite capabilities
- Test skipping
- Suite skipping
- Dynamic skipping support via runtime executions
- Test one or more suites exclusively
- Test one or more tests/specs exclusively
- Test labels and tagging
- Testing debug output stream
- Clickable suite titles to filter test execution
Related: TestBox- CFML BDD/Unit Testing Framework Released
TestBox is very simple to install and start using. All that is required is for a single line command to be entered into CommandBox, Ortus Solutions’ CLI manager. You may choose to install either the bleeding edge version or most current stable version of TestBox.
// Install latest stable version
box install testbox
// Install bleeding edge version
box install testbox@be
TestBox also comes with MockBox, Ortus Solutions’ mocking and stubbing framework.
Related: 080 Assert Control Over Your Legacy Applications (TestBox Quick Start) with Ed Bartram
Mocking and MockBox
“A mock object is an object that takes the place of a ‘real’ object in such a way that makes testing easier and more meaningful, or in some cases, possible at all”. -Scott Bain (Emergent Design The Evolutionary Nature of Professional Software Development)
During unit testing of ColdFusion CFCs, you will reach a point where a single class will have multiple external dependencies. Therefore, in order to properly test this particular class, we must be able to mock and obtain full control of this behavior. This is vital to the principles of unit testing which state that a unit must be tested in isolation. Mock objects need to be created. They will act as test oriented replacements for collaborators and dependencies.
These mock objects may be created manually, but this is where MockBox shines. MockBox is an automation tool used to help you mock dynamically and at runtime. Using MockBox helps you to easily test the behavior of components as you now control all expectations. As your object oriented apps become increasingly complex, mocking becomes essential. However, standard mocking has its limitations. By using MockBox, you will be able to apply a TDD style methodology to your unit testing and accelerate it.
There are many ways to ensure that your ColdFusion projects turn out great. It is very important to test and mock your developing projects. Don’t get caught off guard by not doing proper testing. Break free from the trend of not using appropriate frameworks. Give your CF apps the best chance of success by using them. These are just some base principles to unit testing, BDD, TestBox, and MockBox. Through practice and use of these development tools and methodologies, you will be able to produce quality CFML applications every time.
Originally published at teratech.com on September 4, 2018.