Test Design StudioGo to Previous Topic: CA0208 - Document private variablesGo to Next Topic: User-Specific Rules

Naming Convention Rules

Summary

When code is being authored by multiple people, coding conventions play a significant role in helping ensure that the collective code is presented in a consistent format. How we name our language elements (e.g. variables, constants, functions) helps define the intent of that item and can provide additional context.

A common convention in most languages is to name constants with all upper-case letters so that when you see a constant in use, it's clear by the convention that the code references a constant. Conversely, someone who named a variable user all upper-case letters might incorrectly convey that a value is a constant when it is not.

Warning:    Beta Feature: This functionality is currently being provided in beta form. Only VBScript is supported at this time, and the implementation could change before final release. If you encounter any issues or limitations with this feature, please contact support@patterson-consulting.net.

Rules Engine

The most common theme among naming conventions is that there is no common convention. Test Design Studio cannot possibly provide pre-defined rules that work for everyone. To accommodate the various styles in use throughout the industry, we have instead developed a rules engine where you can define the specific naming conventions you want to implement. The rules are contained in a single XML-formatted file that supports multiple forms of verifications to be selectively applied to your language elements.

To help get you started, we have supplied the following rule definitions that you can use directly or as a starting point for your own custom rules. Both files are located in the installation folder of Test Design Studio under the "CodeAnalysis" sub-folder.

File name Description
rules.xml This rule is configured by default and includes the most basic naming conventions that are widely adopted in the industry for use in VBScript. These rules include:
  • Constants are all upper-case letters with an underscore (_) between words
  • Functions, Subs, Properties, and Classes are "Pascal Case" which is generally defined as a mix of upper- and lower-case letters where the first letter of each word is upper-case and the other letters are lower-case.
  • Variables and Parameters are "Camel Case" which is similar to "Pascal Case" except the first word is all lower-case and then each subsequent word starts with upper-case letter.
rules.sample.typePrefix.xml

This rule includes all the functionality of the default rule file, but shows how you can implement a prefix for variables of certain data types. A common practice in type-less languages like VBScript is to name items (particularly variables and parameters) with a prefix to indicate the expected type of data to be stored there. A variable holding string-based data might start with "s" or "str". Integer-based data might start with "i" or "int".

This file uses macros to define the prefix values for each data type, and then reuses that prefix in the various rules. You can easily change the prefix to match your company's standards and all the rules will be updated.

Tip:    Even if you don't use type-based prefixes, this file serves as an excellent example of how macros can be used in your rules as well as more complex conditions and verifications.
Warning:    Do not modify these files directly! These pre-defined files may be updated in future releases of Test Design Studio and installing the update could overwrite your changes. Instead, we recommend you create a copy of the file and make your modifications on the copy.

Rule Definition File

Rules are defined in a single XML-formatted file. The following defines the syntax and options available for defining your rules.

Rules Node

The top-level node in the file must be named Rules.

[xml] - Copy Code
<Rules Language="VBScript" Version="1">
</Rules>

Available Attributes:
AttributeDescription
Language(Required) Defines the language to which the rule applies. Only "VBScript" is supported at this time.
VersionDefines the version of the syntax used in the file. All rules should set the version to "1" to differentiate from possible future versions.

Available Child Nodes:
NodeDescription
MacrosA collection of text-based macros to be used through the rule definition.
RuleGroupA group of one or more rules that can share common conditions or attributes.
RuleAn individual rule.

Macros and Macro Nodes

Macros are used to define a string of text that can be re-used throughout your rule file. The sample rule files show how regular expression patterns can be defined for common patterns like "Pascal Case" and "Camel Case". Using these macros not only limits the regular expression definition to a single location, it creates more readable rules since the name of a macro can be more meaningful than a hard-to-read regular expression pattern.

[xml] - Copy Code
<Rules Language="VBScript" Version="1">
  <Macros>
    <Macro Name="PascalCase">([A-Z][a-z0-9]*)+</Macro>
    <Macro Name="camelCase">[a-z][a-z0-9]*([A-Z][a-z0-9]*)*</Macro>
  </Macros>
</Rules>

The Macros node takes no attributes and the Macro node is the only recognized child node.

Available Attributes for Macro node:
AttributeDescription
Name(Required) The name used to refer to the macro.
(Inner Text)(Required) The inner text of the node defines the textual value that will be represented by that macro.

Using Macros

A macro is used by inserting the text %name% where "name" refers to the name of the macro (e.g. %PascalCase% or %Property-Kind%). Macros are typically used in the Value attribute of a Condition or Verify node or within the Description node of a rule.

The following example illustrates how a user-defined macro called IntegerPrefix is used in multiple locations along with some built-in macros for properties (see "Properties" table below for more details on those macros).

[xml] - Copy Code
<Rule Name="Prefix integer variables and parameters with '%IntegerPrefix%'">
  <Condition Property="Type" Test="EqualsIgnoreCase" Value="Integer" />
  <Verify Property="IdentifierName" Test="StartsWith" Value="%IntegerPrefix%" />
  <Description>The %Property-Kind% '%Property-IdentifierName%' contains integer data and should begin with '%IntegerPrefix%'.</Description>
</Rule>

Rule Node

The Rule node defines the criteria for applying the logic to determine if a rule is valid for the given input, when it has been valid, and how violations are reported.

[xml] - Copy Code
<Rules Language="VBScript" Version="1">
  <Rule Name="The name of my rule" Certainty="75" FixCategory="DependsOnFix" MessageLevel="Warning">
    <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Constant" />
    <Verify Property="IdentifierName" Test="Matches" Value="%UPPER_CASE%" />
    <Description>This is the message that will be displayed in Error List when the rule is violated.</Description>
  </Rule>
</Rules>

Available Attributes:
AttributeDescription
Name(Required) A brief summary of the rule
Certainty(Default = 50) A value from 0 to 100 representing the percentage of certainty that the rule has been applied (e.g. 90 indicates high degree of certainty).
FixCategory (Default = DependsOnFix) Classifies the impact of fixing the issue identified by the rule. Valid entries:
  • Breaking - The fix will likely break other code (e.g. completely changing the name of a function will require calls to that function to be updated).
  • NonBreaking - The fix will not break other code (e.g. changing the case of a variable since VBScript is not case-sensitive).
  • DependsOnFix - The fix may or may not be a breaking changed depending on what you have to do to correct it.
MessageLevel (Default = Warning) Classifies the criticality of the issue identified by the rule. Valid entries:
  • Information - The rule is for informational purposes only.
  • Warning - The rule warns of a potential problem, but it may not have to be addressed.
  • Error - The rule warns of a critical problem that must be addressed.

Available Child Nodes:
NodeDescription
ConditionA condition that must be met for the rule to be applied. You can define multiple conditions.
OrConditionUsed to group two or more conditions where only one of the conditions must be met.
VerifyThe verification to perform.
DescriptionThe message that is displayed in the Error List when an applied rule does not pass verification.
Help(Optional) A URL to be associated with the rule that provides additional information or documentation. This can be accessed from the context menu within the Error List tool window.

RuleGroup Node

This node is used to group one or more Rule nodes. Attributes and Conditions defined on a RuleGroup node will be applied to all child Rule and RuleGroup nodes contained under it. This help prevent duplication when multiple rules share the same attributes.

The following attributes from the Rule node can also be applied to the RuleGroup node (see above for details):

Available Child Nodes:
NodeDescription
ConditionA condition that must be met for rules within this group to be applied. You can define multiple conditions.
OrConditionUsed to group two or more conditions where only one of the conditions must be met.
RuleDefines a Rule that will inherit certain properties from this group.
RuleGroupDefines a RuleGroup that will inherit certain properties from this group.

Condition and Verify Nodes

Both of these nodes are used to define tests that will be performed. The Condition node defines one or more tests to determine if the rule is applied to the input. The Verify node defines a test to perform on applied rules to determine if the input passes the rule.

[xml] - Copy Code
<!-- ... -->
  <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Constant" />
  <Verify Property="IdentifierName" Test="Matches" Value="%UPPER_CASE%" />
<!-- ... -->

Available Attributes:
AttributeDescription
PropertyThe name of a property to be evaluated. See the list of properties below.
TestThe type of test to be performed against the property. See the list of available tests below.
ValueThe expected property value based on the type of test being performed.

Properties

The following tests are available for use in Condition and Verify nodes:
Property NameDescription
Source The source of the item being evaluated by the rule. The only supported source at this time is "Declaration".
Tip:   Use text macro %Property-Source% to refer to this value.
Kind The type of item being evaluated. The following types are valid for "Declaration" sources:
  • Class
  • Function
  • Sub
  • Property
  • Variable
  • Parameter
  • Constant
Tip:   Use text macro %Property-Kind% to refer to this value.
IdentifierName The name of the identifier associated with the source (e.g. variable name, parameter name, function name).
Tip:   Use text macro %Property-IdentifierName% to refer to this value.
Type The type of data associated with the source. For Variables, Parameters, and Constants, this is the data type stored in the item. For Functions and Properties, this is the data type returned. Subs have no data type since they do not return anything. The type of a Class is the class itself. This value corresponds to the value attribute used in XML comments. Example value include (but are not limited to):
  • Boolean
  • String
  • Integer
  • Long
  • Double
  • Currency
  • Object
  • Variable
  • Scripting.Dictionary
  • Any other Prog ID
  • The name of a Class
  • The name of an Enum
Tip:   Use text macro %Property-Type% to refer to this value.
Scope The scope of the source. The following scopes are valid:
  • Public
  • Private
  • Dim
  • Static
Tip:   Use text macro %Property-Scope% to refer to this value.
ParameterMode (Parameter Kind Only) Indicates the mode through which the parameter was passed. The following modes are valid:
  • ByRef
  • ByVal
Tip:   Use text macro %Property-ParameterMode% to refer to this value.

Tests

The following tests are available for use in Condition and Verify nodes:
Test NameDescription
EqualsThe property must exactly match the given value.
EqualsIgnoreCaseThe property must match the given value, and character casing is ignored.
DoesNotEqualThe property must not exactly match the given value.
DoesNotEqualIgnoreCaseThe property must not match the given value, and character casing is ignored.
MatchesThe property must match a regular expression.
MatchesIgnoreCaseThe property must match a regular expression, and character casing is ignored.
DoesNotMatchThe property must not match a regular expression.
DoesNotMatchIgnoreCaseThe property must not match a regular expression, and character casing is ignored.
StartsWithThe property must start with the given value.
StartsWithIgnoreCaseThe property must start with the given value, and character casing is ignored.
DoesNotStartWithThe property must not start with the given value.
DoesNotStartWithIgnoreCaseThe property must not start with the given value, and character casing is ignored.
EndsWithThe property must end with the given value.
EndsWithIgnoreCaseThe property must end with the given value, and character casing is ignored.
DoesNotEndWithThe property must not end with the given value.
DoesNotEndWithIgnoreCaseThe property must not end with the given value, and character casing is ignored.
ContainsThe property must contain the given value at any location.
ContainsIgnoreCaseThe property must contain the given value at any location, and character casing is ignored.
DoesNotContainThe property must not contain the given value at any location.
DoesNotContainIgnoreCaseThe property must not contain the given value at any location, and character casing is ignored.
IsEmptyThe property value must be empty or filled with white space. Note that the Value attribute is not necessary for this test.
IsNotEmptyThe property value must not be empty or filled with white space. Note that the Value attribute is not necessary for this test.

OrCondition Node

All Condition nodes defined at the same level in the file must be met for a rule to be applied. You can use the OrCondition node to group one or more condition for a scenario where only one of the conditions has to be met instead of all of them. The following code example shows how an OrCondition can be used to match on either a Sub or a Function.

[xml] - Copy Code
<!-- ... -->
  <OrCondition>
    <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Sub" />
    <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Function" />
  </OrCondition>
<!-- ... -->

Example

The following is a detailed example demonstrating many of the features and capabilities of the rules file.

[xml] - Copy Code
<Rules Language="VBScript" Version="1">

  <Macros>

    <!-- Character Casing -->
    <Macro Name="UPPER_CASE">[A-Z]+[A-Z0-9_]*</Macro>
    <Macro Name="PascalCase">([A-Z][a-z0-9]*)+</Macro>
    <Macro Name="camelCase">[a-z][a-z0-9]*([A-Z][a-z0-9]*)*</Macro>

    <!-- Variable/Parameter Prefix -->
    <Macro Name="StringPrefix">str</Macro>
    <Macro Name="IntegerPrefix">int</Macro>
    <Macro Name="LongPrefix">lng</Macro>
    <Macro Name="BooleanPrefix">bln</Macro>
    <Macro Name="DateTimePrefix">dtm</Macro>
    <Macro Name="DoublePrefix">dbl</Macro>
    <Macro Name="CurrencyPrefix">cur</Macro>
    <Macro Name="ObjectPrefix">obj</Macro>
    <Macro Name="VariantPrefix">var</Macro>

  </Macros>

  <RuleGroup>

    <Condition Property="Source" Test="Equals" Value="Declaration" />

    <!-- Constants-->
    <Rule Name="Constants should be upper case">
      <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Constant" />
      <Verify Property="IdentifierName" Test="Matches" Value="%UPPER_CASE%|\[%UPPER_CASE%\]" />
      <Description>Constants should start with a letter, can contain upper-case letters and numbers, with words separated by an underscore.</Description>
    </Rule>
  
    <!-- Methods, Properties, & Classes -->
    <Rule Name="Functions, properties, and classes should use pascal case.">
      <OrCondition>
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Function" />
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Sub" />
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Property" />
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Class" />
      </OrCondition>
      <Condition Property="IdentifierName" Test="DoesNotEqualIgnoreCase" Value="Class_Initialize" />
      <Condition Property="IdentifierName" Test="DoesNotEqualIgnoreCase" Value="Class_Terminate" />
      <Verify Property="IdentifierName" Test="Matches" Value="%PascalCase%|\[%PascalCase%\]" />
      <Description>The %Property-Kind% '%Property-IdentifierName%' should begin with an upper-case letter, can contain letters and numbers, and each new word begins with an upper-case letter.</Description>
    </Rule>
  
    <!-- Variables & Parameters -->
    <RuleGroup Certainty="90" FixCategory="DependsOnFix" MessageLevel="Warning">
      <OrCondition>
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Variable" />
        <Condition Property="Kind" Test="EqualsIgnoreCase" Value="Parameter" />
      </OrCondition>
      <Rule Name="Variables and parameters should use camel case.">
        <Verify Property="IdentifierName" Test="Matches" Value="%camelCase%|\[%camelCase%\]" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' should start with a lower-case letter, can contain letters and numbers, and each new word begins with an upper-case letter.</Description>
      </Rule>
  
      <Rule Name="Prefix string variables and parameters with '%StringPrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="String" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%StringPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains string data and should begin with '%StringPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix integer variables and parameters with '%IntegerPrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Integer" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%IntegerPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains integer data and should begin with '%IntegerPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix long variables and parameters with '%LongPrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Long" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%LongPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains long integer data and should begin with '%LongPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix boolean variables and parameters with '%BooleanPrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Boolean" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%BooleanPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains boolean data and should begin with '%BooleanPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix date/time variables and parameters with '%DateTimePrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="DateTime" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%DateTimePrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains date/time data and should begin with '%DateTimePrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix double-precision variables and parameters with '%DoublePrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Double" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%DoublePrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains double-precision data and should begin with '%DoublePrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix currency variables and parameters with '%DateTimePrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Currency" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%CurrencyPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains currency data and should begin with '%CurrencyPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix object-based variables and parameters with '%ObjectPrefix%'">
        <Condition Property="Type" Test="EqualsIgnoreCase" Value="Object" />
        <Verify Property="IdentifierName" Test="StartsWith" Value="%ObjectPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains object-based data and should begin with '%ObjectPrefix%'.</Description>
      </Rule>
      <Rule Name="Prefix untyped variables and parameters with '%VariantPrefix%'">
        <OrCondition>
          <Condition Property="Type" Test="EqualsIgnoreCase" Value="Variant" />
          <Condition Property="Type" Test="IsEmpty" />
        </OrCondition>
        <Verify Property="IdentifierName" Test="StartsWith" Value="%VariantPrefix%" />
        <Description>The %Property-Kind% '%Property-IdentifierName%' contains untyped data and should begin with '%VariantPrefix%'.  Alternatively, use XML-based comments to define the type of the %Property-Kind% so it will not be seen as Variant.</Description>
      </Rule>
     
    </RuleGroup>
  
  </RuleGroup>

</Rules>