Home > soar > Introducing SoarUnit

Introducing SoarUnit

August 1st, 2010 Leave a comment Go to comments

The history of testing in Soar is short and not very happy. This is especially true for automated testing, where the tools have generally been ad hoc, proprietary, and hard to use. I am personally responsible for some of these tools. Despite all this, I’m foolishly taking another foray into the land of Soar unit testing. This new effort is called SoarUnit and is part of the JSoar suite. However, since the JSoar community is even tinier than the overall Soar community, I’ve made sure that SoarUnit is compatible with both Soar implementations.

(For more complete docs and examples, see the SoarUnit wiki page, and the Bebot source code. There’s a snapshot (20100801) of JSoar with the latest SoarUnit on the JSoar downloads page.)

SoarUnit UI

The one advantage that this effort may have over previous Soar testing attempts is that I developed it at the same time that I was actively working on Soar code. When I first started working on Soar99 and Bebot, my testing strategy was very ad hoc. I had a big Soar file that looks something like this:

   source "test1.soar"
   run
   excise --all

   source "test2.soar"
   run
   excise --all

   ... and so on ...

To run my tests, I’d just source the file and eyeball the trace for errors, which, if you’re familiar with Soar, you’ll know are usually pretty easy to spot. Of course, there were some drawbacks to this approach:

  • Manually checking for success/failure is painful. The “green bar” is so much nicer.
  • To add a single new test, I had to add another three lines to¬† my “master test” file.
  • There was no way to put more than one test in a file, necessitating either a bunch of duplicate code, or some confusing trickery with the source command.
  • When a test failed, I had to manually source it to debug.

Basically, all the same problems you get when manually testing code in any other language.

So, with 30 or so ad hoc tests already built, I started working on SoarUnit. Here’s the basic structure of a testcase file:

setup {
   ... Code run before every test. Here you can source code under test,
       setup test data, propose initialization opreators, etc ...
}

test "name of test" {
   ... Code for an individual test. Here you put any code
       you need for the test. When the test's success condition's
       have been detected, a rule should call the (pass) RHS function.
       Similarly, there's a (fail) RHS function for detecting failures ...
}

... More tests ...

Nice and simple.

I think the existing tests were key to how well development has gone. Every previous attempt I’ve made for testing Soar code has been based on imagining how someone might use such a framework, without any real-world requirements to build from. Although I’ve only been working on it a little more than a week, SoarUnit already has:

  • Test case discovery by file name pattern
  • Multiple tests per file
  • Setup blocks to handle code shared by multiple tests
  • A graphical interface similar to Eclipse’s JUnit view (see below)
  • Single-click debugging from the user interface
  • Support for both JSoar and CSoar 9.3.0 (CSoar requires that a SOAR_HOME environment variable be set so it can find native libraries and stuff)
  • Basic code coverage reporting

Best of all, I’ve used it a lot on Bebot and Soar99 and it’s honestly really nice. I did a major refactoring, basically renaming all of the major data structures and operators in the library, and it was a breeze. I guess that’s the point of having tests…

What’s Next?

I’m going to keep working on SoarUnit to support my own Soar development. There are still some obvious holes and open questions.

One area that’s always plagued talk of testing Soar code is I/O. How do you test an agent independent of the environment it will run in. I’m currently of the mind that, like unit testing in every other language, this is where mocking comes in. With a few rules, an agent can easily simulate static structures on the input-link to driver tests. If things get too complicated, one option is simple integration with soar2soar, where for each test, a helper agent would be created to simulate the environment. There are other options as well (plugins, external processes, etc), but none of them maintains the simplicity I want for SoarUnit. For every configuration parameter, you lose a user and with Soar there aren’t that many to start with.

The other open question is whether SoarUnit is effective for testing idiomatic Soar code. Soar has very little encapsulation or modularity which can make it difficult to isolate code for testing. The problems I’m solving with Bebot are very procedural, so they’re easy to test, but I’m not sure that’s true for most Soar code. I’d like to work through creating tests for some of the Soar tutorial problems and see how it goes.

Categories: soar Tags: , , ,