Data tables, or "other" tables?

285 views
Skip to first unread message

Pekka Nikander

unread,
Apr 23, 2012, 2:53:51 AM4/23/12
to robotframe...@googlegroups.com
[I'm a new RF user (but I did read the manuals, did search the archives, and did read the source code), so apologies if this is already covered by the documentation or has been discussed in the past.]

We are using RF for embedded system testing, and have a number of test cases that essentially share a few data or configuration tables, like the following example:

=========== ======== ======
Registers Address Length
=========== ======== ======
MIDV 0xC0 16
HV 0xC1 16
...
=========== ======== ======

We already know how to represent this as a set of variables, as a list variable table (so that we can :FOR) over it, how to represent it as a dictionary in a Python fixture, or how to write a variable file for it. However, all of those have the drawback that the result is not easy to understand for our hardware engineers, who have little Python knowledge, or has extra syntactic ugliness that is hard for them to remember when modifying test cases.

Hence, we would like to define "other" or data tables in Robot framework, and use them from the fixtures. The idea would be that RF would parse those tables just like Keyword, Test case, Setting, Metadata etc tables, but it would not do anything with them by default. However, one could use the table names (like "Registers") as arguments to keywords, and the underlying fixture could then iterate over the table using the table name as a handle to an API.

Apparently in 2.7.1. there is no such feature. Has such a feature been considered for a future version?

If not and if I want to implement it myself, where should I start? The parsing package appeared to be obscure enough that I couldn't make it much sense of it. Should I perhaps create a new table populator by monkey patching the tablepopulators subpackage?

Is there somewhere an API for iterating over the existing tables, so that I perhaps could initially misuse a Keywords table for this? (I didn't find one, but I guess there must be.)

--Pekka Nikander

Mikko Korpela

unread,
Apr 23, 2012, 11:32:56 AM4/23/12
to pekka.n...@senseg.com, robotframe...@googlegroups.com
Hi Pekka,

I don't think that similar functionality has been suggested before.

What kind of syntax for the use of these data tables should be used in
the keyword / test code?

Currently I think that RF will just ignore any unidentified tables. So
you could also try to implement something like what your suggesting
with a python library that would parse the test case file and your
custom tables from there..

The parsing and running modules in RF are one of the oldest parts in
the RF code base so my knowledge about them is too limited to give you
any good instructions on how to use them. There are plans to replace
at least the running part with a new implementation in the near future
so I don't know how stable an in-house monkey patched version would
be..

Kind Regards,
Mikko Korpela

> --
> You received this message because you are subscribed to the Google Groups "robotframework-users" group.
> To post to this group, send email to robotframe...@googlegroups.com.
> To unsubscribe from this group, send email to robotframework-u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/robotframework-users?hl=en.
>

Pekka Nikander

unread,
Apr 23, 2012, 2:28:30 PM4/23/12
to Mikko Korpela, robotframe...@googlegroups.com
Hi Mikko, thanks for your help, inline below more.

> What kind of syntax for the use of these data tables should be used in
> the keyword / test code?

Maybe something like this. First, in a test case, something like the following:

========= ============== ==== ======
Test case Keyword Arg Arg
========= ============== ==== ======
Foo Write register MIDV 0x20
========= ============== ==== ======

Then, in a fixture:

def write_register(self, register_name, value, registerbank="Registers"):
registers = robot.api.get_dict_from_table(registerbank)
(address, length) = registers[register_name]
emulator.raw_write(address, length, value)

Of course, that is a somewhat silly example, but it gives you the idea.

Anyway, in this particular example, "Registers" would be the table name, from the first cell. get_dict_from_table would be convenience function that would turn the table into a dictionary, row by row, by associating the string in the first column with a tuple of strings in the following columns.

There could also be other convenience functions, like accessing the table by row index (returning a tuple or list of cells on the row), by column name, etc.

I haven't really thought out what would be the underlying APIs and data structures, though.

> Currently I think that RF will just ignore any unidentified tables.

That's the impression I got from reading the source code.

> So you could also try to implement something like what your suggesting
> with a python library that would parse the test case file and your
> custom tables from there..

Sure, but as there is already infrastructure for that, why not to reuse?

BTW, how do I get the test case file name through the Robot APIs?

> The parsing and running modules in RF are one of the oldest parts in
> the RF code base so my knowledge about them is too limited to give you
> any good instructions on how to use them. There are plans to replace
> at least the running part with a new implementation in the near future
> so I don't know how stable an in-house monkey patched version would
> be..

So, should I perhaps ask at the -devel list instead? Or do people hang around on both?

>> =========== ======== ======
>> Registers Address Length
>> =========== ======== ======
>> MIDV 0xC0 16
>> HV 0xC1 16
>> ...
>> =========== ======== ======


--Pekka Nikander

Mikko Korpela

unread,
Apr 23, 2012, 4:02:10 PM4/23/12
to robotframework-users, Pekka Nikander
Hi Pekka,

You can get the name of currently executed test case from ${TEST NAME}
that can be accessed at least by using BuiltIn library

For example:
from robot.libraries.BuiltIn import BuiltIn

def testname():
   return BuiltIn().get_variables()['${TEST NAME}']

And yes this is the list that is followed by all the active core team
developers but I my self haven't really yet worked with the part of
code in question - I can find out more tomorrow (if no one else
happens to reply to you before that).

We can be also found from IRC freenode/#robotframework.

> --
> Mikko Korpela

--
Mikko Korpela

Tatu aalto

unread,
Apr 23, 2012, 4:38:52 PM4/23/12
to mikko....@gmail.com, robotframework-users, Pekka Nikander
Ugh

So you want to give dev some familiar format to work with Robot. Is there some reason why you can not use the data driven style (1) and reST format (2). The data driven style provides the test template and hides the keyword from the developer.  The reST format is kind a same that you are presenting and you could format the table names as you see fit, expect the first one (3). Also the embedding the arguments to keyword name brings you more flexibility to use the test template (4).

Could this solve your problem instead?

-Tatu

(1) http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.1#data-driven-style
(2) http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.1#restructuredtext-format
(3) http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.1#ignored-data
(4) http://robotframework.googlecode.com/hg/doc/userguide/RobotFrameworkUserGuide.html?r=2.7.1#embedding-arguments-into-keyword-name

Pekka Klärck

unread,
Apr 23, 2012, 5:06:50 PM4/23/12
to pekka.n...@senseg.com, Mikko Korpela, robotframe...@googlegroups.com
2012/4/23 Pekka Nikander <pekka.n...@senseg.com>:

> Mikko wrote:
>
>> So you could also try to implement something like what your suggesting
>> with a python library that would parse the test case file and your
>> custom tables from there..

This is what I would recommend too. In addition to having the data in
the test case files themselves, you could obviously also have them in
external files e.g. in plaint text or CSV format.

> Sure, but as there is already infrastructure for that, why not to reuse?

I'm afraid reusing the current parsing logic for this purpose would be
somewhat complicated and the benefits pretty small. The main problem
of reusing is that Robot parses the date from the beginning into Robot
related entities (test cases, keywords, ...) but you would probably
want to get raw tabular data. Changing the logic so that the raw data
is available would be possible (and would probably be better design
anyway) but would also require quite a bit of work. In the end
benefits for this particular use case might still be pretty small,
because you probably wanted to convert that raw data into some more
meaningful domain-specific objects.

With the above limitations in mind, I believe writing a custom parser
for your data is easier than reusing Robot's parsing logic. Generic
parts of the parser, such as parsing tabular data into a matrix or
dictionary, could possibly be released as a separate reusable module.
Then also other library developers could easily use it, and perhaps it
would also have uses outside Robot Framework ecosystem.

Cheers,
.peke
--
Agile Tester/Developer/Consultant :: http://eliga.fi
Lead Developer of Robot Framework :: http://robotframework.org

Pekka Nikander

unread,
Apr 24, 2012, 1:06:38 AM4/24/12
to Tatu aalto, robotframework-users
Hi Tatu,

Thanks for your suggestions.

We are already using data driven style (1) for our test cases, and using the Github Wikis (cf. FitNesse) to store our test cases using reST (2). [So you see why I'm writing the examples as I am :-)] And we do use embedded arguments (4).

In my original mail I wrote that I could _misuse_ the Keyword tables and read them from the fixtures (but I don't know how -- I would need to figure out.) However, I haven't figured out how to use a template with a Keyword table. Furthermore, most probably we would even need to set the template through a variable, as the table would need different interpretation in different context.

Anyway, the real problem is that we need this _data_ in several (potentially tens) different test cases, and each time it is being used in a slightly different way. In essence, the data is part of our description of the system under test, something that (AFAIK) is typically hidden in fixtures. Where we perhaps are not so typical is that, in our case, this SUT description should be readily accessible to people that are not familiar with the fixtures (nor code), as they are hardware engineers. I guess there might be also other domains having similar kind of a situation, e.g. in communications protocol engineering, where there are people who know the protocol messages and state machines but not necessarily the fixtures or the implementation.

But thanks Tatu, you gave me an idea. Perhaps I could read the reST directly using docutils. I just need to figure out the plumbing on how to find the relevant resource files names through RF so that I can press them with docutils.

--Pekka Nikander

Pekka Nikander

unread,
Apr 24, 2012, 1:12:46 AM4/24/12
to Pekka Klärck, Mikko Korpela, robotframe...@googlegroups.com
>> Mikko wrote:
>>> So you could also try to implement something like what your suggesting
>>> with a python library that would parse the test case file and your
>>> custom tables from there..

On 2012–04–24, at 0:06 , Pekka Klärck wrote:
> This is what I would recommend too. In addition to having the data in
> the test case files themselves, you could obviously also have them in
> external files e.g. in plaint text or CSV format.

Ok, I stand corrected. :-)

I'll try to parse our reST directly with docutils.

>> Sure, but as there is already infrastructure for that, why not to reuse?
>
> I'm afraid reusing the current parsing logic for this purpose would be
> somewhat complicated and the benefits pretty small. The main problem

> of reusing is that Robot parses the [data] from the beginning into Robot


> related entities (test cases, keywords, ...) but you would probably
> want to get raw tabular data. Changing the logic so that the raw data
> is available would be possible (and would probably be better design
> anyway) but would also require quite a bit of work.

I'm fraid agree. The tablepopulators stuff doesn't look like that easily
expandable. But perhaps you plan to rewrite that anyway :-)

> In the end
> benefits for this particular use case might still be pretty small,
> because you probably wanted to convert that raw data into some more
> meaningful domain-specific objects.

Well.... right. Though the objects are likely to be mostly just dicts,
or simple subclass wrappers around it.

> With the above limitations in mind, I believe writing a custom parser
> for your data is easier than reusing Robot's parsing logic. Generic
> parts of the parser, such as parsing tabular data into a matrix or
> dictionary, could possibly be released as a separate reusable module.
> Then also other library developers could easily use it, and perhaps it
> would also have uses outside Robot Framework ecosystem.

If I manage to put together the reST docutils table extractor into
anything meaningful, I'll let you folks know. You can then decide
whether to expand that with HTML and CVS support, and perhaps package
it along with RF. I know that I'll be too busy to properly package it,
I'm afraid.

--Pekka

Jussi Malinen

unread,
Apr 24, 2012, 12:58:27 PM4/24/12
to pekka.n...@senseg.com, Pekka Klärck, Mikko Korpela, robotframe...@googlegroups.com
Hi!

With Rammbock [1] we faced a rather similar issue: How to present structured data in Robot files.

We chose to introduce keywords for presenting data structures and other keywords for accessing the result.

So in simplified form we could have:
*** Keywords ***
Message structure
New message
u32 foo 0xcafebabe
u32 bar 0xdeadbeef
u32 what 0
u32 ever 11
Client sends message

Here the u32-keywords just add data to an internal list, that is then used when calling "Client sends message".

Maybe you could do something similar? Introduce a keyword or keywords which only add data to some data structure, and then this data would be available to your other keywords?

You can also have several *** Keywords *** tables in a suite file, so you could have keywords dedicated just for presenting data in a separate table if you like.

Cheers,
Jussi

[1] https://github.com/robotframework/Rammbock

Bryan Oakley

unread,
Apr 24, 2012, 1:14:06 PM4/24/12
to robotframe...@googlegroups.com
I've done something similar in the past. I create a keyword named ":" that appends to an internal list:

| | using the following data:
| | : | u32 | foo  | 0xcafebabe

| | : | u32 | bar  | 0xdeadbeef
| | : | u32 | what | 0
| | do something clever

Though, we've pretty much abandoned that approach and now make heavy use of "...":

| | using the following data | do something clever
| | ... | u32 | foo  | 0xcafebabe
| | ... | u32 | bar  | 0xdeadbeef
| | ... | u32 | what | 0

We then just have to make "do something clever" iterate over the data 3 cells at a time.
Reply all
Reply to author
Forward
0 new messages