Python vs TTCN-3

Some time ago computing scientists Bernard Stepien and Liam Peyton from the University of Ottawa compared Python with TTCN-3. TTCN-3 means Testing and Test Control Notation and it is domain specific language specifically designed for writing tests in the domain of telecommunication. In almost any category poor Python just loses in comparison.

A few things of the presentation are just odd. At several places it contains Python code that is not even consistent. Examples: on slide 42 an “else if” construct is used instead of the correct “elif”. On slide 13 fields are not assigned to self which leads to code that fails to run. But leaving this carelessnes aside there is something important that estranges an experienced Python programmer. Take slide 12 for example. Here the authors state:

TTCN-3 templates to Python
  • TTCN-3 templates could be mapped to Python object instances.
  • However, there are serious limitations using the above technique with Python.
  • Python objects are practically typeless.

Then the presentation goes over 18 slides just to explain how bad plain Python classes are for serving the same purposes as TTCN-3 templates. Although this is correct why should anyone care? If you want to experience an exhilarating effect you have to turn grapes into wine and do not expect the same fun from grape juice. Then you can compare cheap wine with premium one. That’s also why people are used to compare Django to Ruby On Rails and not Django to Ruby or Rails to Python. That’s why libraries and frameworks exist in the first place.

So what about modeling a Template class that has same functionality as a TTCN-3 template? Here is a first attempt:

class Template(object):
    def __init__(self):
        self._frozen = False
        self._fields = []        
 
    def __setattr__(self, name, value):
        if name in ('_fields', '_frozen'):
            object.__setattr__(self, name, value)
            return
        if self._frozen:
            raise RuntimeError("Cannot set attribute value on a frozen template")
        if name not in self._fields:
            self._fields.append(name)
        object.__setattr__(self, name, value)
 
    def __eq__(self, other):
        if len(self._fields)!=len(other._fields):
            return False
        else:
            for f_self, f_other in zip(self._fields, other._fields):
                val_self  = getattr(self, f_self)
                val_other = getattr(self, f_other)
                if val_self != val_other:
                    return False
            return True
 
    def __ne__(self, other):
        return not self.__eq__(other)
 
    def freeze(self):
        self._frozen = True
 
    def clone(self):
        T = Template()
        T._fields = self._fields[:]
        for field in T._fields:
            setattr(T, field, getattr(self, field))
        return T

The Template class manages an internal _fields attribute that contains the attribute names created by __setattr__ dynamically. This is done to preserve the sequential order of the fields on template comparison. In the current implementation there aren’t any fields marked as optional and it will take additional effort to introduce them and modify __eq__.

It is now easy to demonstrate the behavior of wildcards. First we have to introduce another class for this purpose:

class Wildcard(object):
    def __eq__(self, other):
        return True
 
    def __ne__(self, other):
        return False

For any object X which is compared to wildcard it is always X == wildcard == True. So following template instances are equal:

templ_1 = Template()
templ_1.field_1 = wildcard
templ_1.field_2 = "abc"
 
templ_2 = Template()
templ_2.field_1 = "xyz"
templ_2.field_2 = wildcard
 
assert templ_1 == templ_2

A Pattern class can be created in the same way as the Wildcard class:

class Pattern(object):
    def __init__(self, regexp):
        self.pattern = re.compile(regexp)
 
    def __eq__(self, other):
        try:
            return bool(self.pattern.match(other))
        except TypeError:
            return True
 
    def __ne__(self, other):
        return not self.__eq__(other)

An ‘==’ comparison of a Pattern instance with a string will match the string against the pattern and yield True if the string could be matched and False otherwise.

So it is perfectly possible to reproduce most aspects of TTCN-3 templates by just a few lines of Python code. On the downside of TTCN-3 it isn’t possible to do things the other way round. No matter how hard you work in TTCN-3 it is impossible to create new TTCN-3 types showing interesting behavior. Pythons expressiveness is miles ahead.

  1. As a tester/developer I’ve always wondered why people want to separate testing and development in general, but having a separate testing language is just insane. A general purpose language with testing related modules/tools is so much better idea.

    About the comparison: The example on page 21 with trying to use two __init__s and complaining that only the latter is used makes it obvious that these guys don’t know any Python. Default values for methods are explained pretty early in any tutorial — and they are so much easier to use and clearer than having multiple methods with different signatures.

    A simple solution for ‘‘ and ‘?’ wildcards in Python is using fnmatch module (with a caveat that ‘‘ doesn’t match newlines).

  2. Ionel Maries says:

    I would dismiss the comparison on the spot. It’s full of misconceptions about python and typing theory. Take for example this outrageous statement in the pdf slides: “Known limitations of Python: OO language but not strongly typed” – python IS strongly typed AND duck typed. I wonder if the authors took any classes on typing theory.

  3. Joseph Lisee says:

    They also said that python has no Eclipse plugin which is just not true. Pydev is a great eclipse plugin for Python and I use it all the time.

  4. kay says:

    Pekka, the predecessor of TTCN-3 can be tracked back to the late 80s. TTCN-3 can be considered as a pre-OO and pre-UML attempt to define something like “model based testing” and it is still widely used for conformance tests in some industries. It is obvious that the authors are biased and try to promote TTCN-3 and there wouldn’t be anything wrong about it if their arguments weren’t just flawed.

  5. Petri Savolainen says:

    I have programmed in Python for years, and while I am no real expert on TTCN-3, I have nevertheless taught a day-long beginner-level course on it once, and visited the TTCN-3 conference in Berlin a few years ago.

    Given that Bernard Stepien’s presentation was given at a TTCN conference, it is quite natural that it aims to highlight benefits of TTCN. The circles are small, and he’s more or less a semi-regular presenter there. It is sad that the presentation is so clearly constructed purely for the purpose of making TTCN-3 look good, without any real attempt at a sound academic-quality comparison. Or maybe its just incompetence.

    It is good to try & understand the differences though, so this kind of comparisons serve a purpose regardless 😀

    But getting into categorical argument about special-purpose testing language vs. using a general-purpose language for testing would be just plain silly. It all depends on purpose, context and requirements. For example, it would be silly to use TTCN-3 for direct testing of Python programs, but I would rather pick TTCN-3 for low-level telecommunications protocol conformance and interoperability testing any day. The testing-specific features built right into TTCN-3 are particularly useful for such purposes and contexts, and while they could be replicated in Python, the implementations would always be less elegant.

  1. There are no trackbacks for this post yet.

Leave a Reply