7/12/2008

Even More Guns for Embedded Development

A while back Benoit saw the light of using modern languages (Ruby in that case) to help in developing embedded software, which still in most cases is developed in C for very well known reasons. I though I will throw additional ingradient to this soup. We are also using Python for our test-driven development, for acceptance test-driven development to be precise. There are few concepts that has lead us to do this.


1. You remember wrapping thinly with hexagonal architecture, right?

2. Company that I work for has a long history of using embedded PC simulation system called E-SIM from Mentor Graphics. This product has evolved, but we are using the old version.

3. E-SIM simulation tool has a Python API wrapper

A continuum is to develop own embedded acceptance test framework using Python, right? Well, we did it anyway. It is fairly simple, really. E-SIM communicates with the application interfaces using the mechanism called channels. There is a Windows service running called Communication Manager. And this fellow is responsible for gathering and sharing values in these channels to various C applications and our test driver written in Python. Indeed, we can have several applications running on one PC and simulate multi-device/processor/board systems as we wish. A channel can be a package in communication, a binary input as push button, binary output as LED, and so on.

Now, wanting to be able to write acceptance tests in a domain language that could be more readily understood by the business, we created a script parser using Python's reflection. This test driver parses the test script file and launches all the application .exe's as needed and then stimulates and senses the system using of E-SIM channel accessors. Sounds simple? The nice part is that it really is simple.

These tests run automatically on our continuous integration server, but we also have a GUI which simulates UI of a real system. Now we can watch the UI in action during the test sequence scripts.

Here is a snippet of .test acceptance test script written in (almost) domain language


sendFire 0,1,2,3,Delay Fire
wait 2
sendDelayed 0,1,100
wait 2
checkRow 1,FIRE in zone 00021/1



Here is the reflection part of the parser in Python. I have no idea how good of a Python code this is being an average embedded C programmer, but it looks simple to me.



for line in tp.getTestLines():
self.currentScriptLine = line
self.currentScriptLineNumber += 1

if len(line) > 1:
elements = line.split(' ',1)

try:
if len(elements) > 1:
getattr(self, elements[0])(elements[1].lstrip(' '))
else:
getattr(self, elements[0])()
except:
self.myReporter.addWarning()
self.warning("Could not execute line: %s" % line)




And finally here is a simple method in the TestDriver class. You can see that the method's name matches the action word in the test script snippet above. The rest of the test script line is passed as an argument to the method.



def checkRow(self, parameters):
elements = parameters.split(',')
row = int(elements[0])

expected = string.replace(elements[1], "\n", "")
actual = self.currentLCD_Rows(row)

self.checkEqual( expected, actual )




Similar approaches are Atomic Object's Systir, and Exoftware's Exactor. These can be labeled as script frameworks in contrast to table frameworks like FIT/Fitnesse.

No comments: