robotframework icon indicating copy to clipboard operation
robotframework copied to clipboard

Use term "compound keyword" instead of "user keyword"

Open pekkaklarck opened this issue 2 years ago • 16 comments

Robot can have two kinds of keywords. Lowest level ones are implemented in libraries using Python and higher level ones can be created using Robot's own syntax. We currently call these keywords "library keywords" and "user keywords", respectively. The former name is fine, it makes it clear that these keywords are implemented in libraries, but the latter name is a bit odd. Users creating tests may not have created "user keywords" they are using or they may have also created "library keywords".

I believe that term "compound keyword" would be better than "user keyword". It doesn't concentrate on who has created the keyword, but instead makes it clear that the keyword is a combination of different parts. If others have even better ideas, please propose them in comments!

The main reason I believe we should change the term now is that as part of adding start/end_keyword methods to the listener API v3 (#3296), we are going to expose also model objects representing user/compound keywords. We probably need to add separate methods for them and I wouldn't like to add start/end_user_keyword if the term would be changed in the future. Adding start/end_library_keyword and start/end_compound_keyword sounds much better to me. In addition to the method name, the term will affect the names of the model objects.

This issues consists of the following tasks:

  • [ ] Agreeing on the term to use.
  • [ ] Updating the User Guide
  • [ ] Making sure existing public APIs use the new term in code and in documentation.

New public APIs obviously need to use the new term as well, but that is covered by their respective issues. Internal code can be updated when otherwise modified.

pekkaklarck avatar Aug 25 '23 19:08 pekkaklarck

I do agree that User keyword is maybe not the best name. Often, when introducing people to writing libraries, either in Python syntax or Robot language, I refer to Python keywords and Resource keywords. When working with testers that do not write libraries themselves, I refer to Resource keywords and Library keywords, because these are the terms one needs to use when importing the library. Which leaves the case where testers write some local keywords in the test suite file, which I then call Tester keywords. Well, that's just what I do now, but I'll be sure to use the official names ones they are improved ;-)

I don't immediately see how Compound keywords is a better name. Library keywords can be implemented as compound keywords just the same; run_keyword() calls from Python also does the trick. Especially in companies where there is sufficient Python knowledge, it is often easier to stick to just one style and skip the resource files.

Looking at it from the opposite direction, I am wondering what the motivation is to split up the listener based on the way the keyword was written? In which situations does this benefit a user that is writing the listener? Couldn't the information just be an argument or property of an argument in the listener function? Maybe expose what the source (file) of the keyword is? That would open up a wider range of choices for the implementer of the listener, but keeps the interface more narrow.

JFoederer avatar Aug 28 '23 06:08 JFoederer

Resource keyword is a good name otherwise, but it doesn't really work when referring to keywords created in suite files directly. In documentation we could use a different name for them, but in code they are represented by same class. In that usage ResourceKeyword would be misleading.

It's true that library keywords can call other keywords but that's pretty rare. I wouldn't consider that a big problem.

The reason to separate library keywords and user/compound/resource keywords in listener is that the latter can be modified. You can add new keywords or control structures, modify or remove existing, and so on. The idea is that these listener methods are called only after we have resolved what a keyword call like Keyword arg actually refers to and have the appropriate keyword available. This can be still discussed, but the discussion belongs to #3296.

pekkaklarck avatar Aug 28 '23 08:08 pekkaklarck

Thank you, that is clear. I now understand the technical reason for splitting it up.

Given that the reason for splitting up is mainly technical, I am still doubtful whether the difference should be presented as prominently as suggested. It starts to feel like a composite pattern from which I would then borrow the terms leaf and composite keyword, but only for people who need to get into these details. E.g. by adding a flag to the start/end_keyword call attributes, indicating that it is either a leaf or a composite keyword. If your current listener doesn't need the new details you can easily switch to the new version. (If there are no other dependencies I overlooked)

Getting back to this specific issue. Maybe there is no need to make a change in terminology after all. Ignoring the technical details, Library keywords are written by Python programmers and User keywords are written by Robot Framework users. It is not that bad after trying to come up with better alternatives.

JFoederer avatar Aug 28 '23 14:08 JFoederer

I agree with @JFoederer that I really don't see "compound keyword" as any better description for what we call "user keyword". Actually I think it might be a little less clear.

emanlove avatar Aug 30 '23 18:08 emanlove

The problem I have with "user keywords" is that users can create libraries. In general I'd like to lower the barrier between just using the framework and extending it with libraries and I believe terminology matters. I'd thus like to have some other term but it doesn't need to be "compound". Does anyone have proposals?

If there's no proposal that's considered clearly better than "user keyword", sticking with the old term is fine as well. There's plenty of work associated with the terminology change and not doing anything would avoid that.

pekkaklarck avatar Sep 04 '23 18:09 pekkaklarck

The main reason I believe we should change the term now is that as part of adding start/end_keyword methods to the listener API v3 (https://github.com/robotframework/robotframework/issues/3296), we are going to expose also model objects representing user/compound keywords. We probably need to add separate methods for them and I wouldn't like to add start/end_user_keyword if the term would be changed in the future. Adding start/end_library_keyword and start/end_compound_keyword sounds much better to me. In addition to the method name, the term will affect the names of the model objects.

I understand the desire to settle this now for reasons of clarity and stability with listener methods names. What I am wondering is why would there need to be separate methods for user/compound keywords? From one perspective I see how distinguishing the two makes sense. But then down at an execution model would not a single method for start/end be sufficient?

emanlove avatar Sep 04 '23 19:09 emanlove

The best way to have a good idea, is to have lots of ideas... so let's throw a few in:

  • User keywords vs Library keywords
  • Compound keywords vs Direct keywords
  • Composite keywords vs Leaf keywords
  • Robot keywords vs Coded keywords
  • Low-code keywords vs Python keywords
  • Local keywords vs External keywords
  • Custom keywords vs Library keywords

If there is no clear winner, maybe what we have is as good as any

JFoederer avatar Sep 05 '23 12:09 JFoederer

Because our active native English speaking users prefer the User Keyword term, it's clear there would be no benefits with the terminology change. The change would, however, require a lot of work. Let's forget about that and go forward with User Keywords!

pekkaklarck avatar Oct 18 '23 19:10 pekkaklarck

I would like to reopen. I think compound keywords are just more descriptive. I missed the discussion… 😞

Snooz82 avatar Nov 24 '23 22:11 Snooz82

The ISO 29119-5 does name them composite keywords and simple keywords I do not like the simple and in German I do prefer atomic keywords as a phrase for those that are not made of others.

Snooz82 avatar Nov 24 '23 22:11 Snooz82

I thing the language model has a pretty good point here.

quote: In the context of keyword-driven testing, it's important to choose terms that are clear, intuitive, and reflective of the functionality of the keywords. For the two types of keywords you've described, here are suitable terms:

  1. Composite Keywords: For keywords that are made of other keywords, the term "Composite Keywords" is fitting. The word "composite" implies a combination or assembly of parts, which aligns well with the idea of these keywords being constructed from other existing keywords. It's a term that's easily understood and reflects their layered nature.

  2. Primitive Keywords: For keywords that are implemented directly by code, the term "Primitive Keywords" could be used. "Primitive" in programming often refers to basic, low-level constructs that are not decomposed further. This term suggests these keywords are the fundamental building blocks in keyword-driven testing, directly tied to code, and not built from other keywords.

The choice of these terms helps in clearly differentiating between the two types of keywords based on their composition and level of abstraction. "Composite" and "Primitive" are terms widely used in various fields, including programming and mathematics, making them recognizable and understandable to people with different backgrounds, especially those familiar with technical concepts.

Snooz82 avatar Nov 24 '23 22:11 Snooz82

Choosing between "Composite" and "Compound" involves subtle nuances in meaning and connotation:

Composite vs. Compound:

  • Composite: This term suggests a structure made from multiple distinct elements, each retaining its identity within the larger assembly. In software, it often implies a modular and hierarchical arrangement, which aligns well with keywords constructed from other keywords.
  • Compound: While similar, "compound" often implies a more complex integration, where the individual components may lose their distinct identities in the process of forming the compound. In chemistry, for instance, compound elements form a new substance altogether.

"Composite" is preferred because it better conveys the idea of maintaining the identity of individual keywords within a larger, assembled keyword.

Snooz82 avatar Nov 24 '23 23:11 Snooz82

I still feel both compound and composite are simply wrong. Just yesterday I refactored a library keyword that was lacking in the analysability department. One of the steps in the process was replacing some direct method calls to other keywords with run_keyword. The benefit I see in this is:

  1. Programming can stay in Python. I minimize the use of IF from .robot or .resource files and I have yet to use my first TRY/EXCEPT there.
  2. It improves the logs. Instead of having long chunks of text, that lost their context, I get the nice expandable keywords to guide my users through what is happening.

So, in my opinion, Library keywords are created and maintained by programmers, User keywords by domain specialists. Whether or not something becomes a composite keyword depends on how you want to communicate to your users through the logs. Also, like in my example, keywords often are already composite, but it just doesn't shown due to the way the other keywords are called.

JFoederer avatar Nov 25 '23 15:11 JFoederer

Also the term primitive does not cover it, in my opinion. A typical architecture is to have technical libraries that build an abstraction on top of the System Under Test, to make it controllable from a programmatic setting. This layer should be independent from the chosen automation framework.

Robot keyword libraries are there to bridge the gap from the Domain Specific Language (keywords) to the technical domain. They use the technical libraries for this and, as such, they are by no means primitive in this context.

JFoederer avatar Nov 25 '23 16:11 JFoederer

@JFoederer I understand your opinion, but i do not fully agree.

Library keywords do not need to be any technical. It is just the "lower" end of the Keyword Levels. Below a library keyword it is not keywords anymore. Even that you call BuiltIn().run_keyword does not make it a keyword. It is still Python code. And keywords composed of other keywords are composite. But still Library Keywords may be Domain Specific.

I typically make a difference between the term Level and Layer. Levels are just defining if it is an atomic library keyword or if it is a keyword used in the tests. That can actually mean that there is just one level. But levels like High Level or Library Level do not say anything about if it is technical or business logic. The Layers on the other hand do have a relation to its abstraction. A Business Layer keyword can be on Library Level or a keyword belonging to the Adaptation Layer (Click, or Get Attribute) can be used as High Level keyword in a test, if you are testing technical things.

So the separation of Composite vs Library/Primitive/Atomic keywords is just a technical definition. It has nothing to do with the layers they are belonging to.

However i can understand the naming of User Keyword because it can be created by users. But that, as Pekka already said, does also apply for Library Keywords and therefore it is imho the wrong term.

And even though i am not a huge fan of the ISO 29119-5 it is still a Standard that already gives a definition of the term Composite Keyword. And i must say, that it exactly tells what it is. A keyword composed of other keywords.

But i would prefer to have this discussion in Slack! Lets please involve others.

Snooz82 avatar Nov 25 '23 16:11 Snooz82

There was long discussion on Slack about this but no clear consensus on what to do. The status quo is keep using the user keyword team and I believe we cannot do anything else before RF 7.0.

The only thing RF 7.0 changes related to this are the new start/end_user_keyword methods in the listener v3 API. If we later agree on the terminology change, renaming those methods in backwards compatible manner isn't too complicated.

pekkaklarck avatar Dec 19 '23 23:12 pekkaklarck