Testing can focus on various aspects of a system or software. These aspects can include a focus on functionality, or what the system does, or on non-functionality, how the system does it what it does. It can also include testing on the system’s structure, changes to the system, if changes are successful, and if any unintended side effects happened. These four levels of test types are called functional, non-functional, structural, and change related. In this post, I will examine functional testing and testing pertaining to changes.
Functional testing involves testing the specified behavior or “what it does” and may be performed at all test levels. Specification-based testing is also known as “black-box testing” since it tests without reference to the internal structure of the component or system (Black, 2012). The testing focus for functionality testing is usually suitability, interoperability, security, accuracy, and compliance, according to ISO 9126 standards. There are two main approaches to using this test type: requirements-based or business-process based.
Requirements-based testing can take the requirements from the table of contents of a specification document and use them as a test basis for creating the tests. Business-based requirements are focused more on use cases from business processes. In a payroll system, for example, business processes would include when an employee joins the company or how often employees are paid.
Testing related to changes involves confirmation and regression testing. After a failed test, a defect is found and fixed. Confirmation testing involves re-testing the code in the same way and make sure that the new code did not bring in any unintended side effects and can be used at all test levels. Regression testing is used as a follow up to confirmation testing.
Regression testing involves executing test cases that have already been completed and most likely passed the last time they ran. We must organically grow the regression test suite over time in line with the software just as we do with unit tests. Should one of these tests now fail, we will have found a new defect introduced to the system. Regression testing should be performed at all test levels, specifically when a new version of the software is created, or the software environment changes.
As a programmer, we are going to be naming lots of variables, classes, and methods. According to Uncle Bob in Clean Code, we should name a variable with the same care we do in naming a first-born child. After all, we are going to need to be able to call it, know what it’s for, and not confuse it with any other variables in our classes.
When we name with care, we name with “intention-revealing” names. Naming well saves you more time in the long run, saves everyone more time, and prevents a snowball of bad things happening to your precious code. The names we choose should answer the big questions:
Why does it exist? What does it do? How is it used?
We need to be able to tell what the code is doing. In the example picture, it is very easy to see what the purpose is of the last three names versus the first name. Explicit names help immediately see what is going on in the code. If you MUST use a single letter name, it is best practice to use it as a local variable inside a short method. The length of a name should correspond to the size of its scope.
Using a name like h, we would have to mentally map what this variable is doing, translating it in our brain to what it actually does, using much more memory. Clarity is king. Use your powers for good naming practices to write code that everyone can understand. Pretend like the next person who will read your code is a violent psychopath who knows your address. It’s serious business!
Class and Method Names
This is something that needs to be written on your computer or tattooed on your arm or put anywhere you can see it, like an affirmation you are practicing, only programmer edition.
Class names should have a noun or noun phrase. Class names should not be verbs.
Methods should have verb or verb phrases. Accessors, mutators, and predicates should be named for their value and prefixed with get, set, and is according to the javabean standard. (“Oracle Java Technologies | Oracle,” 2019).
Don’t be cute in naming. Clever names are memorable only to people who share the same humor and some of us are the only ones laughing at our jokes. I know I’m funny, but others may not think so. Clarity is more important than entertainment. Our cleverness only goes so far as our cultural slang. Naming something dirtNap() meaning kill() or wipeout() meaning DeleteItems() is cute, but the latter is understood by all. A consistent lexicon is worth its weight in gold for the programmers who must use your code.
Other Important Naming Concepts
Pick one word for an abstract concept and stick with it. Using fetch, retrieve, and get as similar methods in different classes goes back to using too much mental memory. Ask yourself some questions about what these methods are doing and see if they are all serving the same purpose to choose an appropriate word.
Don’t Pun. Converse to using one word per abstract concept, do not use the same word for two purposes. Doing so would be a pun. Using “one word per concept”, could end up with a lot of classes using an “add” method as described in the book. If we are using the word for consistency rather than intent, it can get very confusing. Ask yourself what the method is actually doing so you know if you need to name it “insert” or “append”.
Use Solution Domain Names. Programmers will be reading your code so go ahead and use terms that other programmers understand like algorithm names, math terms, and pattern names.
Use Problem Domain Names. Problem domains refers to all the information that defines the problem (i.e. the problem you are solving with code). If there are no programming or computer science terms for what the code is doing, use the name from the problem domain. Good programmers and designers have the important task of separating solution and problem domain concepts.
Add Meaningful Context, But Not Gratuitous Context. Most of the time we have successfully added meaningful context by using good naming, separation of concerns, and well-defined classes. As a last resort, you may have to add some prefixing. If you saw firstName, lastName, street, houseNumber, city, state, and zipcode in a method, you would assume it’s an address. If city was used alone in a method, would you assume it’s part of an address? The context can be added by prefixing with addrState, addrCity, etc so it’s explicitly part of an address.
This doesn’t mean to do this always. Adding gratuitous context can be very confusing, like prefixing every method with the acronym of the application. “ABCFirstName, ABCLastName, ABCStreetAddress” are too much. Shorter names are generally better than long ones when they are clear.
Following some of these rules and asking yourself the important questions about your code will help get you thinking about what and why you are naming things and keeping the code understandable for all, saving you many headaches in the future. Happy coding!