First, some code cleanup. I had a lot of hard-coded paths in my fixtures. All fixtures used to start with:
from fit.ColumnFixture import ColumnFixture
import sys
blogger_path = "C:\\eclipse\\workspace\\blogger"
sys.path.append(blogger_path)
import Blogger
This is clearly sub-optimal and requires a lot of copy-and-paste among modules. To simplify it, I turned the blogger directory into a package by simply adding to that directory an empty file called __init__.py. I also moved Blogger.py (the main functionality module) and its unit test module, testBlogger.py, to a subdirectory of blogger called src. I made that subdirectory a package too by adding to it another empty __init__.py file. Now each fixture module can do:
from fit.ColumnFixture import ColumnFixture
from blogger.src.Blogger import get_blog
There's one caveat here: the parent directory of the blogger directory -- in my case C:\eclipse\workspace -- needs to be somewhere on the Python module search path. In FitNesse it's easy to solve this issue by adding C:\eclipse\workspace to the classpath via this variable definition which will go on the main suite page:
!path C:\eclipse\workspace
When invoking the Python interpreter from a command line, one way of making sure that C:\eclipse\workspace is in the module search path is to add it to the PYTHONPATH environment variable, for example in a .bash_profile file. For our example though, the fixture modules are always invoked within the FitNesse/PyFIT framework, so we don't need to worry about PYTHONPATH.
Now to the SetUp page functionality. If you create this page as a sub-page of a suite, then every test page in that suite will automatically have SetUp prepended to it by FitNesse. I created a SetUp page (its URL is http://localhost/FitNesse.BlogMgmtSuite.SetUp) with the following content:
!|BloggerFixtures.Setup|
|setup?|
|true|
I also created the corresponding Setup.py fixture, with the following code:
from fit.ColumnFixture import ColumnFixture
from blogger.src.Blogger import get_blog
blog_manager = None
class Setup(ColumnFixture):
_typeDict={
"setup": "Boolean"
}
def setup(self):
global blog_manager
blog_manager = get_blog()
return (blog_manager != None)
def get_blog_manager():
global blog_manager
return blog_manager
The setup method invokes the get_blog function from the Blogger module in order to retrieve the common Blogger instance used by all the fixtures in our test suite. I did this because I wanted to encapsulate the common object creation in one fixture class (Setup), then have all the other fixture classes cal the get_blog_manager function from the Setup module. Another benefit is that only the Setup module needs to know about the physical location of the Blogger module, via the line:
from blogger.src.Blogger import get_blog
All other fixture classes need only do:
from Setup import get_blog_manager
since they are in the same directory with Setup.py.
A SetUp page can also be used to pass values to the application via methods in the Setup class. Assume we need to pass the path to a configuration file. One way of accomplishing this is to define a FitNesse variable in the SetUp page, like this:
!define CONFIG_PATH {C:\config}
The FitNesse syntax for referencing a variable is ${variable}, so we can pass it as an argument to our Setup fixture like this:
!|BloggerFixtures.Setup|${CONFIG_PATH}|
|setup?|
|true|
When the page is rendered by FitNesse, ${CONFIG_PATH} is automatically replaced with its value, so on the rendered page we'll see:
BloggerFixtures.Setup | C:\config |
setup? | |
true |
In the Setup fixture class, we can get the value of the argument like this:
config_path = self.getArgs()[0]
One other thing we could do in the SetUp page is to include the DeleteAllEntries fixture, so that we can be sure that each test page will start with a clean slate in terms of the blog entries.
I moved the old code from parts 1 and 2 of the tutorial here. You can see the new code here.
1 comment:
Very Informative blog
Post a Comment