In the last articles from the High-Quality Automated Tests we talked about coding styles and various tools that can help you to force them automatically. In this publication, I am going to talk about different naming guidelines your tests should follow so that they are more readable and maintainable by other people.
While ago when we were working on the first version of the BELLATRIX test automation framework, I did this research while I was working on a similar feature for our solution.
General Naming Guidelines
Always use English. Avoid abbreviations except accepted ones- clientsCnt vs clientsCount. Avoid hard-to-pronounce names- dtbgRegExPtrn vs dateTimeBulgarianRegExPattern
Use Meaningful Names
Always prefer meaningful names. It is more important that the name to be clear than that it to be short. Favor readability over brevity. Do not use anything that the large majority of people who are not experts in a given field would not know the meaning of immediately. Names should answer these questions:
What does this class do? What is the intent of this variable?
What is this variable/class used for?
Correct
TaxesCalculator, clientsCount, Math.PI, configFileName, GenerateReport
Incorrect
k, k9, k5, f44, KJJ, button3, variable, temp, tmp, temp_var, something, someValue
Names Should Be Meaningful in Their Context
Whether a name is meaningful or not depends on its context (its enclosing type).
Meaningful Names
- Generate() in the class TaxesGenerator
- Find(string fileName) in the class FileFinder
- Deposit(decimal amount) in the class Account
Meaningless Names
- Generate() in the class Program
- Find(string name) in the class Program
Naming Classes and Structures C#
Use the following formats: [Noun] or [Adjective] + [Noun]
Correct
Student, FileSystem, SupportTicket, Constants, MathUtils, RecurringBillingPurchase, Order
Incorrect
Move, FindUsers, Fast, ExtremlyFast, Optimize, Verify, FastFindInDatabase
Do NOT Use Underscores in Class Names
Do not use underscores, hyphens, or any other non-alphanumeric characters. Do not use Hungarian notation. Avoid using identifies that conflict with keywords or widely used programming languages.
Consider ending the name of derived classes with the name of the base class.
Correct
public partial class TwelveMonthRecurringBillingOrdersPanelAdminBasePage : AdminBasePage
{
}
Incorrect
public partial class 12Month_RecurringBilling_OrdersPanel_AdminPage: AdminBasePage
{
}
Names of Generic Type Parameters
Name generic type parameters with descriptive names unless a single-letter name is completely self-explanatory and a descriptive name would not add value.
public class ElementsList<TElement> : IEnumerable<TElement>
where TElement : Element
{
public TElement this => GetWebDriverElements().ElementAt(i);
public IEnumerator<TElement> GetEnumerator() => GetAWebDriverElements().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int Count() => GetWebDriverElements().Count();
//...
}
Consider indicating constraints placed on a type parameter in the name of the parameter. For example, a parameter constrained to IElement might be called TElement.
Meaningful Class Names
Correct
SalesOrdersReportEngine engine;
SuggestedOrdersReportEngine engine;
Incorrect
// engine to generete report with sales orders
ReportEngine engine;
//engine to generete report with suggested orders
ReportEngine2 engine;
Do not use abbreviations or contractions as part of identifier names. Do not use any acronyms that are not widely accepted, and even if they are, only when necessary. For example GetWindow rather than GetWin.
Naming Special Classes
Attributes
Attributes- add ‘Attribute’ as suffix.
Correct
BrowserAppAttribute, VideoCaptureAttribute
Incorrect
BrowserApp, VideoCapture
Collection
Collection classes- add ‘Collection’ as suffix.
Correct
ElementsCollection
Incorrect
Elements
Exception
Exceptions- add ‘Exception’ as suffix. Use informative name.
Correct
ElementNotFoundException, StaleElementException
Incorrect
ElementNotFound, StaleElement
Delegate classes - add ‘Delegate’ or ‘EventHandler’ as suffix.
The Length of Class Names
How long could be the name of a class, struct, interface, enumeration, delegate? The name should be as long as required. Don’t abbreviate the names if this could make them unclear. Use your IDE’s autocomplete!
Correct
FileNotFoundException, CustomerSupportNotificationService
Incorrect
FNFException, CustSuppNotifSrvc
Naming New Versions of Existing APIs
Sometimes a new feature cannot be added to an existing type even though the type’s name implies that it is the best place for the new feature. In such a case, a new type needs to be added, which often leaves the framework designer with the difficult task of finding a good new name for the new type.
Use a name similar to the old API when creating new versions of an existing API. Prefer adding a suffix rather than a prefix to indicate a new version of an existing API.
Here is an example from the official Selenium GitHub repository C# bindings.
public interface ITimeouts
{
// New API
TimeSpan ImplicitWait { get; set; }
[Obsolete("This method will be removed in a future version. Please set the ImplicitWait property instead.")]
ITimeouts ImplicitlyWait(TimeSpan timeToWait);
// ... rest
}
Use a numeric suffix to indicate a new version of an existing API, particularly if the existing name of the API is the only name that makes sense and if adding a meaningful suffix is not an appropriate option.
// old API
[Obsolete("This type is obsolete. Please use the new version of the same class, X509Certificate2.")]
public class X509Certificate
{//...}
// new API
public class X509Certificate2 {//...}
It is a good practice not to delete the old version immediately but use the ObsoleteAttribute for a few releases and then delete the old methods or classes.
Naming Interfaces in C#
Following formats are acceptable: ‘I’ + [Verb] + ‘able’ or ‘I’ + [Noun], ‘I’ + [Adjective] + [Noun]
Correct
IEnumerable, IFormattable, IDataReader,IList, IHttpModule, ICommandExecutor
Incorrect
List, iFindUsers, ICheckbox, IMemoryOptimize, Optimizer, FastFindInDatabase, Order
Naming Enumerations
Use a singular type for an enumeration unless its values are bit fields.
public enum CarColor
{
Black,
Blue,
Red,
Cyan,
// ...
}
Use plural type name for an enumeration with bit fields as values, also called flags enum.
public enum ConsoleModifiers
{
Alt,
Control,
Shift,
}
Do not use an “Enum” suffix in enum type names. Do not use “Flag” or “Flags” suffixes in enum type names.
Naming Files in C#
Files with source code should have names matching their content. The file containing a class Client should be named Client.cs
Correct
Checkbox.cs, PurchaseRecurringBillingProducts.cs, SupportTicketsGenerator.cs
Incorrect
Program.cs, SourceCode.java, _d2.cs, WebApplication1.jsp, Page1.aspx
Summary
In the first part of the naming guidelines series of articles we looked at various rules about naming classes, interfaces and enums which can make your tests much more readable and maintainable. In the next publications, we will go through a list of practices for naming methods and variables.
