4
votes

Hello to all RobotFramework users

Problem

We have many keywords at different levels of abstraction and are looking for a simple way to import them while maintaining support for autocompletion etc. in IDEs.

The inheritance could look as follows:

   /---------------------> basic_keywords.robot <---\
  /                             ^                    \
 /                              |                    |
 |  advanced_keywords_1.robot --/            advanced_keywords_2.robot
 |            ^
 |            |
more_advanced_keywords_1.robot

Proposal 1: Import all keywords in all_keywords.robot

all_keywords.robot:

*** Settings ***
Library     SomeLibrary.py
Resource    basic_keywords.robot
Resource    advanced_keywords_1.robot
Resource    more_advanced_keywords_1.robot
Resource    advanced_keywords_2.robot

more_advanced_keywords_1.robot:

# No Import of basic_keywords.robot here!!!
*** Keywords ***
My More Advanced Keyword
    Advanced Keyword   # from advanced_keywords.robot
    Basic Keyword      # from basic_keywords.robot

Import in test suites:

*** Settings ***
Resource   all_keywords.robot

Benefits:

  • This works at execution.
  • With the same line in any of the test suites, we have access to all keywords.
  • We do not need to import the necessary keywords in each of the advanced keywords files, which would lead to double imports.

Drawbacks:

  • Autocompletion etc. is not supported because advanced_keywords.robot does not know about basic_keywords.robot.
  • Imports many (often not used) keywords in test suites, slows down performance (?)

Proposal 2: Reference basic_keywords... in advanced_keywords

Proposed by @Todor

advanced_keywords.robot:

*** Settings ***
Resource    basic_keywords.robot
*** Keywords ***
Advanced Keyword
    Basic Keyword      # from basic_keywords.robot

more_advanced_keywords_1.robot:

Resource    advanced_keywords.robot
# basic_keywords is imported here by advanced_keywords.robot
*** Keywords ***
My More Advanced Keyword
    Advanced Keyword   # from advanced_keywords.robot
    Basic Keyword      # from basic_keywords.robot

Double imports are handled by Robot Framework.

Import in test suites:

*** Settings ***
Resource   more_advanced_keywords_1.robot
Resource   advanced_keywords_2.robot

Benefits:

  • This works at execution
  • Auto completion etc. is supported as the IDE knows where the Advaned Keyword is defined
  • Better control on which keywords are available, faster

Drawbacks:

  • You have to explicitly decide / import which advanced_keywords you use in a test suite.

Double instantiations of the library can be prevented by ROBOT_LIBRARY_SCOPE = 'GLOBAL' in SomeLibrary.py, see Robot Framework makes two instances from the class instead of one and the Robot Framework User Guide

Other Proposals?

There are benefits and drawbacks to both proposals. Any recommendations? What structure would you propose?

2

2 Answers

1
votes

At what level does the resolving not work?

Judging from common sense (and personal experience with PyCharm), in suites that import just basic.robot, the keywords from more_advanced_keywords_1.robot will be resolvable - they are indirectly imported through basic, and thus in the current context.

When editing more_advanced_keywords_1, I don't think there is an IDE which will resolve keywords from advanced_keywords_1 or basic. The reason is that the current file does not have access to them in isolation.

In one usage context (suite A), the consumer may have imported both this file (more_advanced_keywords_1) and another (advanced_keywords_1) and have access to the latter's keywords; but in another context (suite B), the consumer may have imported just more_advanced_keywords_1.
So what would hapen in B, if more_advanced_keywords_1 was referencing a keyword from advanced_keywords_1? It would fail at runtime, as the keyword is not defined (accessible) at this point.
This is the same reason an IDE doesn't resolve the keywords defined in advanced_keywords_1 or basic when editing more_advanced_keywords_1 - it has no access to them in the current context.

You have two options:

  • Bite the bullet and not have IDE resolving in the deeper keyword files; it still will work in the suites, so that's something bearable.
  • Go with double imports - basic imports advanced_keywords_1, and advanced_keywords_1 imports basic; it may sound scary or wrong, but Robot Framework (actually py) manages it just fine. Even circular imports are not causing issues (a imports b, and b imports a).

In the past I had a structure just like yours - a master keyword file, importing in itself 20+ 2nd level resource files, some of them importing 3rd level. I've used the double import and did not run into issues (the only req - no keyword names conflicts).
Since then I moved to more broken-down structure - no master file, the suites import only the resources they need. The reason - lighter and faster initial loading, and mainly - I was sick of having 1000+ keywords constantly available in the current namespace - e.g. present in the autosuggestion :)

0
votes

This is issue related with PyCharm IDE, I made an example with RED Robot Editor which handles inherited resources correctly:

project structure:
  res/basic.robot contains basic kw
  res/advanced.robot imports basic.robot -> all kws from basic are avaliable and validated
  res/even_more_adv.robot imports advanced.robot -> all kw from advanced + all kw from basic
  main_testsuite.robot imports res/even_more_adv.robot -> all kw from even_more + advanced + basic resources are visible

I am pretty sure that RIDE will handle such cases as well although I do not have it installed.