• Documentation
  • Tutorials
  • Case studies
  • White papers
  • Product

What's on this Page

  • Resources
  • Keyword declaration
    • Keyword annotation
  • Keyword inputs
    • Reading the inputs in code
    • Passing inputs from code
    • Passing inputs from the step plan
  • Keyword properties
  • Keyword outputs
    • Custom fields
    • Attachment
    • Measurements
    • Error handling
  • Session
  • step
  • Developer guide
  • Keyword API
Categories: DEVELOPER GUIDE API
This article references one of our previous releases, click here to go to our latest version instead.

Keyword API

A keyword represent your automation code, it can fully automate your workflow or a piece of it that you will pipe to other keywords in the end. To make its execution dynamic you can pass inputs to it; you can as well set its output and status for reporting and integrate it to more complex flows.

Resources

In addition to below documentation, you will find tutorials on the documentation pages as well as examples on github:

  • Examples:
    • .net examples
    • java examples
    • js examples
  • Main classes in javadocs related to Keyword:
    • AbstractKeyword
    • OutputBuilder
  • Tutorials:
    • Simple Keyword
    • Selenium Keyword

Keyword declaration

    In order to communicate with step, the class extends the AbstractKeyword superclass. Each method defining a keyword will have to be annotated with the annotation Keyword, will use no arguments and will be of return type void. More details about this class can be found in the javadoc.

    public class MyKeywords extends AbstractKeyword{
    
    	@Keyword
    	public void myKeyword() {
    	   //my automation
    	}
    }

    In order to communicate with step, the class extends the AbstractScript superclass. Each method defining a keyword will have to be annotated with the annotation Keyword, will use no arguments and will be of return type void.

    namespace STEP
    {
        public class Keywords : StepApi.AbstractScript
        {
            [Keyword(name = "My Keyword")]
            public void MyKeyword()
            {
              //your implementation
            }
        }
    }

    Javascript Keyword definition being asynchronous, you must end your keyword with an output.send call.

    exports.MyKeyword = async (input, output, session, properties) => {
      //do some work
      output.send({ result: 'OK' })
    }

    Keyword annotation

    The Keyword annotation as following optional attributes which can be used:

    • name: the name of this keyword. If not specified the method name is used as keyword name
    • properties: the list of properties required by this keyword
    • optionalProperties: the list of optional properties which might be used by this keyword
    • schema: the JSON schema of the input object

    More details on the usage and impact of these attributes are described here.

    Keyword inputs

    A Keyword’s input is a JsonObject with opened types. Thus the developer can choose the type of their arguments but must ensure that they are read accordingly to that type, otherwise the Json reader will throw an error.
    The inputs are passed to the keyword by the caller as described in the following sections.

    Reading the inputs in code

    Inside the Keyword, you can then retrieve your inputs like this:

      String homeUrl = input.getString("url");
      int elementIndex = input.getInt("index",1);
      String homeUrl = (string)input["url"];
      var homeUrl = input['url'];

      Passing inputs from code

      When calling the keyword from your code (for instance in JUnit), you can pass the input as parameter:

        ExecutionContext ctx = KeywordRunner.getExecutionContext(properties, this.getClass());
        // { "url" : "http://step.exense.ch", "index" : 3 }
        Output<JsonObject> output = ctx.run("MyKeyword", "{\"url\":\"http://www.exense.ch\", \"index\" : 3 }");

        Passing inputs from the step plan

        When calling the keyword from a plan, you can pass the input as parameter as shown in below screenshots. More details can be found in the dedicated documentation for plans: DemoKeyword.png

        Keyword properties

        Keywords can also access a map of properties which contains all variables in the scope of execution. This includes variables defined:

        • In the properties of the agent executing the keyword
        • In the plan calling the keyword using “Set”
        • In the parameters defined in the controller
        • In the Keyword configuration such as:
        • $keywordName: the name of the keyword
        • $keywordTimeout: the defined execution timeout of this keyword
        Note that if the same variable is defined at multiple places the values in agent properties override the one in plan which overrides the one in parameter.

        You can retrieve the properties in your keywords from the properties map

          properties.get("myVar");
          properties["myVar"]
          properties['myVar']

          Keyword outputs

          Each keyword can define the content of its output by using the herited “output” object from its parent class. This output builder object is mainly used to:

          • add any key/value pair information for example:
            • for functional checks in plan
            • required for workflow execution
          • set keyword execution status
          • add attachments (pdf, screenshots, exception stack trace as text file…)
          • define response times transactions for RTM

          The method of the OutputBuilder class can be found in the javadoc. The same methods are available for .net. For node.js, you may refer to the source code on github.

          Custom fields

          Below are example on how to add key/value pair information to your keyword’s output object.

            You can refer to the javadoc for the full list of available method. Below is an example for adding a field with a String value:

            output.add("field_name", "field_value");
            output.add("field_name", "field_value");
            output.add("field_name","field_value")

            Attachment

            Below is an example for attaching files to the Keyword’s output:

              byte[] bytes = Files.readAllBytes(file.toPath());
              Attachment attachment = AttachmentHelper.generateAttachmentFromByteArray(bytes, outputName+".log");
              output.addAttachment(attachment);		
              Attachment a = AttachmentBuilder.generateAttachmentForException(exception);
              output.addAttachment(a);
              output.attach({ name: 'screenshot.png', hexContent: data })

              Measurements

              Measurements are automatically created by the controller when executing a keyword. This represents the keyword execution time from the controller view. You can create custom RTM transactions inside your keyword to have finer granularity and/or to enrich the transactions with any key/value pair for analytics purposes.

              The transactions are opened in a stack mode, i.e. when calling the close method, the most recent opened one get closed.

              Refer to the OutputBuilder class’s javadoc for all available methods.

              Example:

                output.startMeasure("CustomMeasureInKeyword");
                //Do some automation work
                output.startMeasure("CustomMeasureInKeyword_Inner");
                //Do some further work to be measured with finer granularity
                output.stopMeasure();//this stop the lasted opened transaction: "CustomMeasureInKeyword_Inner"
                //Add some values to the measurement for analytics in RTM and close the measurement "CustomMeasureInKeyword"
                Map<String,String> measurementData = new HashMap<String,String>();
                measurementData.put("username","Smith");
                output.stopMeasure(measurementData);
                  output.startMeasure("Navigate");
                  //do something
                  output.stopMeasure();
                Measurement API is currently not available in node.js

                Error handling

                step makes a difference between errors which are internal (status “TECHNICAL_ERROR”) and business errors (status “FAILED”). Any unhandled exception raised during the execution of a keyword will end up in the status “TECHNICAL_ERROR”. In order to produce clean reports and leverage this distinction, we highly recommend catching any exception being thrown from within your keywords and handle the situation adequately.

                Technical Errors

                In case your still want your keyword to end up in a technical error state, you may use one of the setError methods available in all supported languages. Likewise, any exception which is thrown from the Keyword will result in a technical error. Remember that this is not the preferred approach as internal error should be reserved for step technical errors.

                Business errors

                To manage properly any errors related to the system or application which is being automated, you may use the setBusinessError method. This will automatically set the status of the keyword execution to “FAILED”.

                If the status as to be determined outside of the keyword, add any meaningful values to the output and perform the check in the caller (i.e. in a step plan).

                In case of exception, you can attach the detailed information to the output object such as the exception message. You can even attach binary content or the exception stack trace to the object by doing so:

                  output.add("ExceptionMessage",e.getMessage());
                  output.addAttachment(AttachmentHelper.generateAttachmentForException(e));
                  Attachment a = AttachmentBuilder.generateAttachmentForException(exception);
                  output.addAttachment(a);
                  output.attach({ name: 'exception.log', hexContent: data })

                  onError hook

                  For each language, overriding the onError hook offers a last chance to manage unhandled exceptions. Each time your keyword function throws an exception, this function will be called with the exception as argument. The return value of this function determine if the exception should be re-thrown (return true) or ignored (return false):

                  • If re-thrown, the status of the execution will be reported as a “TECHNICAL_ERROR” and an attachment of the exception trace will be added
                  • If ignored, the status will be set as “PASSED” and no error will be reported

                  Overriding this function is done as follow:

                    @Override
                    public boolean onError(Exception e) {
                    	/* do here cleanup or exception reporting */
                    	return false;
                    }
                    public override bool onError(Exception e)
                    {
                    	/* do here cleanup or exception reporting */
                      return false;
                    }
                    exports.onError = async (exception, input, output, session, properties) => {
                    	/* do here cleanup or exception reporting */
                      return false;
                    }

                    Session

                    step provides the ability to store data in a session object. This object usually only makes sense when a Session control is used inside the test plan. The session object becomes very useful when passing information or technical objects between keywords (see for example the way we use Selenium’s driver in the next section), especially if the data is difficult or impossible to serialize and de-serialize via the input/output mechanism.

                    You can set any kind of data (primitive types or collections) in the session object by doing so :

                      @Keyword(name="PutToSession")
                       public void putToSession(){
                         session.put("string_key", "Here is my value");
                         session.put("int_key", 3);
                       }
                      session.put("driver", new Wrapper(driver));
                      session.driver_wrapper = createdDriver_wrapper

                      You can then access your data the same way, but you’ll have to cast the data manually back to its original type :

                        @Keyword(name="GetFromSession")
                         public void getFromSession() {
                           output.add("my_string_value", (String) session.get("string_key"));
                           output.add("my_int_value", (int) session.get("int_key"));
                         }
                        Wrapper wrapper = (Wrapper)session.get("driver");
                        const driver = session.driver_wrapper.driver

                        If you’re using a collection, see the method Arrays.copyOf to convert all of its content at once back to the original type.

                        You can then create a test plan using the “Session” control in order to pass the session information trough the Keywords :

                        1520339703046-945.png

                        Once you executed the plan you can see as a result that the session objects have been properly retrieved and displayed as output :

                        1520339785847-159.png

                        See Also

                        • Controls
                        • Event Broker API
                        • step client API
                        • .NET agent
                        • JMeter
                        • Getting Started
                        • Whats new?
                        • Admin guide
                        • User guide
                        • Developer guide
                          • Dev Overview
                          • Keyword API
                          • Measurement API
                          • step client API
                          • Event Broker API
                        • Plugins
                        • Resources
                        Step Logo
                          • Documentation
                          • Tutorials
                          • Case studies
                          • White papers
                          • Product
                          • Getting Started
                          • Whats new?
                          • Admin guide
                          • User guide
                          • Developer guide
                            • Dev Overview
                            • Keyword API
                            • Measurement API
                            • step client API
                            • Event Broker API
                          • Plugins
                          • Resources