Skip to content

How to write custom rules

Bassam Khouri edited this page Nov 28, 2017 · 9 revisions

You can create your own rules by creating classes that inherit from one of the following classes in rflint.common: SuiteRule, ResourceRule, TestRule, KeywordRule or GeneralRule.

Custom rules should be put in the site-rules folder. The only difference between these classes is how and when they are called.

  • Classes that inherit from SuiteRule will be called once for each suite, and be handed an instance of the SuiteFile class as its only parameter.
  • Classes that inherit from ResourceRule will be called once for each resource file, and be handed an instance of the ResourceFile class as its only parameter.
  • Classes that inherit from TestRule will be called once for each test case, and will be handed an instance of the Testcase class as its only parameter.
  • Classes that inherit from KeywordRule will be called once for each keyword, and will be handed an instance of the Keyword class as its only parameter
  • Classes that inherit from GeneralRule behave the same as if they inherit from SuiteRule. This class is useful when you want to write a rule that receives an instance of the RobotFile class, but which may actually do a test that operates against the raw text, or against tables common to both suites and resource files.

Configurable rules

Starting with version 0.5, rules can be configured from the command line with the --configure option. To create a configurable rule you must add a configure method that takes one or more arguments. The arguments will be passed in, in the order that they appear on the command line.

Example - Suite Rule

The following rule checks for duplicate test names. It is a suite rule, since we want it to run once for each suite. In the rule we iterate over all of the testcase names looking for duplicates

from rflint.common import SuiteRule, ERROR

def normalize_name(string):
    '''convert to lowercase, remove spaces and underscores'''
    return string.replace(" ", "").replace("_", "").lower()

class DuplicateTestNames(SuiteRule):
    '''Verify that no tests have a name of an existing test in the same suite'''
    severity = ERROR

    def apply(self, suite):
        cache = []
        for testcase in suite.testcases:
            # normalize the name, so we catch things like
            # Smoke Test vs Smoke_Test, vs SmokeTest, which
            # robot thinks are all the same
            name = normalize_name(testcase.name)
            if name in cache:
                self.report(suite, testcase.linenumber, "Duplicate testcase name")
            cache.append(name)

Example - Configurable Rule

The following example defines a configurable rule that checks the length of each line in a suite or resource file:

class LineTooLong(GeneralRule):
    severity = WARNING
    maxchars = 100

    def configure(self, maxchars):
        self.maxchars = maxchars

    def apply(self, robot_file):
        for linenumber, line in enumerate(robot_file.raw_text.split("\n")):
            if len(line) > self.maxchars:
                message = "Line is too long (exceeds %s characters)" % self.maxchars
                self.report(robot_file, message, linenumber+1, self.maxchars)