How can I test a linked list object pool using FlexUnit 4?

267 views Asked by At

I'm creating an object pool in AS3 that uses a stack as its base data structure (implemented with a linked list). I'm new to FlexUnit, but I'd really like to have some unit tests for my classes (as testing them in a new project would be cumbersome at best).

I've run into some problems trying to track variables, though, as my class members aren't public; I want to be able to test my private methods that only affect members of the class. (Examples include creation of the list, popping a node off of the stack, pushing a node back onto the stack, etc.)

FlexUnit's practices seem to state that you have a separate test class that runs test methods against your classes. However, these classes won't have access to my private variables, and I don't want to have to create getters and setters just for the unit tests. Is there a way around this? Can test methods be added inside the class itself, Python-style, instead of in a test case class?

I apologize if this has been asked before. I'm new to this; I appreciate your help. Let me know if I need to clarify with code snippets or anything.

Edit: I've realized that my data structure is actually a stack, not just a generic linked list. I've updated the question to reflect this.

2

There are 2 answers

2
Vladimir Tsvetkov On

Here's a trick I use with the modern unit testing frameworks. With the modern frameworks, you don't have to extend a TestCase-class or a TestSuite-class. This basic thing gives you such a freedom when you have to deal with testing methods or class fields which aren't public.

Here's the trick:

  1. Let's assume this is the class you need to test:

    package com.npacemo.structures {
    
    class Stack 
    {
        public function push(item:Object):void 
        {
        }
    
        public function pop():Object 
        {
        }
    
        protected var top:Object;
    }
    }
    
  2. Your test can inherit the Stack:

    package com.npacemo.structures {
    
    class StackTest extends Stack 
    {    
        [Test] public function 
        should_push_the_item_on_top():void 
        {
            var item:Object = {name: "Item 01"};
            push(item);
            assertThat(top.name, equalsTo("Item 01"));
        }
    }
    }
    

    If you don't like protected you can also use package-access, but make sure the test and the class under test are in the same package.

It's important not to allow your abstraction to leak with getters and setters methods and public field and methods solely for the purpose of testing. On the other hand if the purpose of your class is to be a data structure then getters and setters make perfect sense. Robert C. Martin discusses in detail the dichotomy between data structures and objects.

8
Amy Blankenship On

If your linked list is going to be at all useful, it will expose some things that will give you access to this information. For instance, in the implementation I posted here http://flexdiary.blogspot.com/2009/12/riadventure-inspiration.html , the list itself isn't really exposed (because a linked list is mainly just its nodes--so to make it more useful, I separated out a cursor that can iterate over the links).

The cursor has an entry point node for the list, so if you wanted you could test that the list has been created by checking for the entry point. But it's passed as a constructor argument, so many people would just take that as read and not bother with a test.

To test that a link has been added at the end, you can iterate to the end and check that the node that is at the end is the one you added (unless your list is circular, in which case you might have a hard time determining that you've reached the end). However, the point of a linked list is that you add links at the point where you are (by setting the nextLink or whatever property of the previous link to the new node--and the previousLink of the old nextLink to the new node if it is linked in both directions), so you might be having this problem because you're trying to create a whole new construct when you're better off just using Array.

Note that if you want to use my implementation, you're welcome to. I wrote it before I started doing TDD, so it has no tests, but I've used it on at least 3 projects now in some form.