5,401,186 members and growing! (16,526 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » Libraries » General     Advanced License: The Code Project Open License (CPOL)

The Case for “PhraseFixture” -- a better DoFixture() for use with FIT and FitNesse Acceptance Testing Framework

By Kenneth Kasajian

The powerful DoFixture() in FitLibrary simulates English like specification. The PhraseFixture proposal takes this to the next level.
C# (C# 1.0, C# 2.0, C# 3.0, C#), .NET (.NET, .NET 3.5, .NET 3.0, .NET 1.1, .NET 2.0), Dev, QA

Posted: 11 Dec 2007
Updated: 11 Dec 2007
Views: 1,654
Bookmarked: 0 times
Announcements



Search    
Advanced Search
Sitemap
2 votes for this Article.
Popularity: 1.51 Rating: 5.00 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
0 votes, 0.0%
4
2 votes, 100.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

The Case for “PhraseFixture”

Background

This articles assumes knowledge of FIT (Framework for Integrated Test), and the FitLibrary.

Overview

For those who’ve used DoFixture from FitLibrary, are probably familiar with the ChatStart example (FitLibraryUserGuide.DoFixture.WritingFixtures). Shw here:

  • The fixture of the first table is a DoFixture, so the created flow fixture object handles the rest of the tables:

ChatStart

  • The second table contains an action, which is mapped into the method connectUser() of the (initial) flow fixture object, as shown below.

connect user

sarah

  • The third table contains two actions which are also applied to the flow fixture object.

user

sarah

creates

fit

Room

user

sarah

enters

fit

Room

What DoFixture attempts to do is to make the table data be more readable. For instance, in the above table, the last row is attempting to be as close as possible to what one would say the phrase in English: “User Sarah enters fit room”. There are two problems here:

  1. The phrase is split across multiple columns of a table, which seems odd. When most people see a table, they typically think of a grid, where the rows are “records”, each column represents some kind of a field. For a TableFixture in FIT, a table is a good method. But DoFixture pushes the table metaphor over its limit. Things get worse when people create tables where each row has different number of columns, based on the number of “parameters”.
  2. The other problem with this is that, even ignoring the fact that the phrase is in a table, reading “User Sarah enters fit room” sounds weird. Shouldn’t “fit” and “room” be swapped? Well, it would sound better, but it wouldn’t work with DoFixture. This is because DoFixture relies upon commands and parameters alternating from one column to the next. In the above five columns containing the words “sarah” and “fit” constitute the parameters, and the words “user”, “enters” and “room” are concatenated to correspond to the fixture method userEntersRoom();. See the class below:

    public class ChatStart : DoFixture
    {
        private ChatRoom chat = new ChatRoom();

        public ChatStart()
        {
            setSystemUnderTest(chat);
        }

        public bool ConnectUser(string userName)
        {
            return chat.connectUser(userName);
        }

        public bool UserCreatesRoom(string userName, string roomName)
        {
            return chat.userCreatesRoom(userName, roomName);
        }

        public bool UserEntersRoom(string userName, string roomName)
        {
            return chat.userEntersRoom(userName, roomName);
        }
    }

Proposal: PhraseFixture()

It’s possible to have a fixture be smart enough to locate the right method even if the words in the phrase did not follow the column alternating sequence. Furthermore, if spaces were used as the delimiter, then the rows would look a lot better. Example:

Chat Start

Connect user sarah

User sarah creates room fit

User sarah enters room fit

Which certainly looks better than:

ChatStart

connect user

sarah

user

sarah

creates

fit

room

user

sarah

enters

fit

room

…and probably easier for the business analyst to type into a table.

They way this can be made to work is simply by trying the combinations of words until a matching method is found, and the unused words become the parameters. So for the fourth row, the words “User”, “Enters” and “Room” get matched to the method UserCreatesRoom(), and the unused words, “Sarah” and “fit” end as the parameters to the method.

Downsides

Every solution has it’s set of problems. Although this reads better than DoFixture, since spaces are used as word delimiters, string parameters that contain spaces will have to be dealt with another way. The proposal is to require is to place strings in quotes. So, for instance, if the user name above was “sarah connor” instead of “sarah”, then the author would have to have entered:

User “sarah connor” enters room fit

which isn’t so bad.

Algorithm

The algorithm is quite simple, and perhaps can be improved. But what it does is like so. As a simpler example, let’s say that the words in the phrase are “Connect user sarah”. It will look for the following method names, and the order ensures that the longest possible name is looked for first:

  • ConnectUserSarah()

  • UserSarah()

  • ConnectSarah()

  • Sarah()

  • ConnectUser()

  • User()

  • Connect()

(The one in bold is obviously the one that will be found since that method exists in the fixture. And since the word “Sarah” is not used in that particular match, that word becomes the parameter to the ConnectUser() function.)

I’m sure it’s possible to come up with a smarter algorithm, but the one included here serves the purpose of demonstrating what is possible.

Supporting Code

        const int cBitsInInt = 32;

        static uint ReverseBits(uint x)
        {
            uint h = 0;
            uint i = 0;

            for (h = i = 0; i < cBitsInInt; i++)
            {
                h = (h << 1) + (x & 1); 
                x >>= 1; 
            }

            return (uint)h;
        }

        static uint ReverseAndShift(uint x, int length)
        {
            return ReverseBits(x) >> (cBitsInInt - length);
        }

        static bool FindMethod(MethodInfo[] methods, string[] columns, out MethodInfo foundMethod, out List<string> parameters)
        {
            uint bits = (uint)(1 << columns.Length);
            for (uint i = bits - 1; i >= 0 && i <= cBitsInInt; i--)
            {
                string s = "";
                parameters = new List<string>();

                uint x = ReverseAndShift(i, columns.Length);
                for (int j = 0; j < columns.Length; j++)
                {
                    if ((1 & x) > 0)
                        s += columns[j].ToLowerInvariant();
                    else
                        parameters.Add(columns[j]);

                    x >>= 1;
                }

                foreach (MethodInfo method in methods)
                {
                    if (method.Name.ToLowerInvariant() == s)
                    {
                        foundMethod = method;
                        return true;
                    }
                }
            }

            foundMethod = null;
            parameters = null;
            return false;
        }


Kenneth Kasajian (ken@kasajian.com)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Kenneth Kasajian



Occupation: Other
Location: United States United States

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Search Search Messages 
 Layout  Per page   
 Msgs 1 to 4 of 4 (Total in Forum: 4) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralNot a good examplememberthompson48227:29 13 Dec '07  
GeneralRe: Not a good examplememberKenneth Kasajian16:48 13 Dec '07  
GeneralGreat Idea.memberunclebob4:25 13 Dec '07  
GeneralRe: Great Idea.memberKenneth Kasajian16:49 13 Dec '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 11 Dec 2007
Editor:
Copyright 2007 by Kenneth Kasajian
Everything else Copyright © CodeProject, 1999-2008
Web12 | Advertise on the Code Project