Metadata-Version: 1.1
Name: funittest
Version: 1.0-beta2dev-r0
Summary: Functional test framework
Home-page: http://www.openplans.org/projects/funittest
Author: Maik Roder and Sylvain Viollon
Author-email: UNKNOWN
License: GPL
Description: Funittest
        
          Funittest is a developers framework for rapidly writing functional
          tests.
          
          Funittest currently has a focus on testing web sites, in particular
          Plone sites, but it could be used to write functional tests
          for any type of application. The main motivation for the development
          if Funittest is to take functional testing to a higer level.
        
        Physical Models
        
          On the lowest level, Funittest makes use of Selenium Remote Control, 
          which directly talks to the browser, and controls it like a normal user
          would.
         
          Check out Selenium RC here:
           
          http://www.openqa.org/selenium-rc/
         
          If you want to use Funittest for another low-level functional testing
          framework, you only need to reimplement the low-level physical object
          models, leaving all higher-level models unchanged.
        
          The following is an example of a physical object model for Selenium
          Remote Control:
        
            class Application:
            
              def login(self, user):
                interpreter.type("__ac_name", user['username'])
                interpreter.type("__ac_password", user['password'])
                interpreter.clickAndWait("submit")
         
          Using a physical object model method like the "login" method above
          is done through the following call sequence:
        
            physical.cmfplone.application.login(user)
        
          The elements in this call sequence :
        
          1. physical: The login method is being a physical method, we need to
             start our call seauence with the physical model. 
          2. cmfplone: There can be different products delivering a login
             method, so we need to use its name next in the call sequence
          3. application: The login method is grouped together with other
             verbs in the "application" cluster, which we need to specify next.
          4. login: The final element of the call sequence is the login
             verb itself, which is called with the user as an argument: "login(user)"
        
          There are good reasons to have such a long call sequence:
        
          1. Easy refactoring by search and replace
          2. No need to import anything, modules are imported dynamically
          3. Test different versions of a product transparently
        
          Let's elaborate on each of these reasons:
        
          1. Easy Refactoring
        
          Defining a good vocabulary is a challenging task. Renaming method names
          or models is very common in the early stages of development as you learn
          more and more about the problem domain.
        
          For example, if you want to know where the physical object model
          method "login" is used in Funittest, or any other model, just do a
          grep like this:
        
          >> grep -R physical.cmfplone.application.login *
        
          If you need to rename the login method to, say "login_user", you 
          can easily use a systematic search and replace. 
        
          Instructions for keeping up with a change of a model name from
          "application" to "app" could be announced like this:
        
            "There is an API change for the physical object model
             called 'application', which has been renamed to 'app'. Please
             make a search for 'physical.cmfplone.application.' and replace it
             with 'physical.cmfplone.app.'."
        
          This kind of API change would be much harder to follow if all of the
          users of Funittest used different import statements. 
        
          The fact that this kind of search and replace is easy to do, and error
          prone, encourages refactoring, which is the cornerstone of building up
          a high quality model step by step as you learn more about the problem
          domain.
        
          2. No imports
        
          In funittest, you only need to import the top level models. Everything
          that is contained in the models is accessed dynamically, and models
          are loaded on the fly.
        
          Just import the physical model and all the rest is taken care of:
        
            from funittest import physical
            physical.cmfplone.application.login(user)
        
          3. Transparent choice of version
        
          Lets count the ways you could do an import for access to the login
          method if you had to import the application cluster:
        
            from funittest.lib import plone214.cmfplone.physical.application
            plone214.cmfplone.physical.application.login(user)
            from funittest.lib.plone214 import cmfplone.physical.application
            cmfplone.physical.application.login(user)
            from funittest.lib.plone214.cmfplone import physical.application
            physical.application.login(user)
            from funittest.lib.plone214.cmfplone.physical import application
            application.login(user)
        
          In any of these cases, you would be fixing the Plone version that
          you import the application cluster from. There is no way around this
          limitation using imports.
        
          Funittest needs to be able to choose the model version on the fly,
          and it does so by choosing the model version transparently:
        
          Use the implementation for the current Plone version:
        
            physical.cmfplone.application.login(user)
          
          Use the implementation for Plone version 2.1.4:
          
            load_product_version("cmfplone", "2.1.4")
            physical.cmfplone.application.login(user)
        
          Use the implementation for Plone version 2.5.0
        
            load_product_version("cmfplone", "2.5.0")
            physical.cmfplone.application.login(user)
        
          As you can see, the call is always the same, not matter what the Plone
          version is:
        
            physical.cmfplone.application.login(user)
        
        Logical Models
        
          The next level of abstraction above the physical model are the logical
          functional models, which contain methods for all user actions, 
          grouped by functionality. The Logical Functional Model hides 
          implementation details in a Physical Object Model that is concerned 
          with interacting with the user interface. Different Logical Functional
          Models can share a common library of user interface methods.
        
          They typically use the lower level physical object models as you can
          see in the following example of a logical functional model called 
          "Application":
        
            from funittest import physical
            class Application:    
              def login(self, user):
                physical.cmfplone.application.login(user)
          
          It is important is to define all of the possible user actions early
          on when defining use cases and functional tests. It is not important
          to already have an implementation for them
        
        Verification
          
          Funittest supports the concept of loosely coupled comprehensive 
          verification. Verification is done before and after the call to
          a logical Functional Model method. Expected state can be compared
          to actual state, and verification can take place all of the time,
          not just in an isolated functional test case.
        
        Test automation stack
          
          Funittest takes over some of the concepts of the test automation
          stack, explained in the Braidy Tester Blog:
          
          http://blogs.msdn.com/micahel/archive/2005/05/04/FromAccountantToScientist.aspx
          
          Some aspects of Funittest are diverging from the ideas of the Braidy
          tester, and also the implementation details can diverge. The general
          ideas still apply, so if you want to dive more into the concepts behind,
          read the whole Braidy Tester blog, and if you are inspired enough, I
          invite you to propose enhancements for Funittest. 
        
        Data Providers
        
          Funittest gets example data from so called data providers, which define
          a data structure for example data and also contain the data itself. 
          There is currently no generation of test data, test data is just moved
          around in a simple dictionary. This simplicity is wanted for the moment,
          and proposals of a different implementation are welcome.
        
          Implementation of Execution Behavior is rudimentary in Funittest, meaning
          that different implementations of a method are chosen by random from a list
          of possible methods implementing the execution behavior. If you have an 
          idea about how to get this done elegantly using Python decorators, let me know. 
        
        Funittest
        
          There are two application areas for Funittest.
          
          1. Write functional tests for a web application
          
          2. Remote control a web application
        
          Funittest is very friendly to the programmer in that it allows the
          execution of functional tests in three modes
          
          1. Dry run mode, simulating the execution of all functional tests.
             Usually takes seconds, and allows you to find errors in your Python
             code instantly.
          
          2. Debug mode, running all functional tests using a browser, but pausing
             in case of an exception. This allows the programmer to debug the
             state of the browser.
          
          3. Run all functional tests automatically.  
        
          Enjoy!
          
        Documentation
        =============
        
        Funittest comes with complete documentation, which you can consult
        by opening the file "doc/index.html" in a browser. The recommended way to
        view the documentation is by launching the Crunchy Frog client using 
        
        cd funittest/doc
        python crunchy.py
        
        Crunchy Frog will open a browser showing the index.html file in the
        docs Folder. You can follow the link to the Funittest tutorials and
        execute Python code interactively. The advantage is that you don't
        need to copy and paste any Python code to a Python interpreter.
        The result of the executed commands are shown inside the browser
        below the code example windows.
        
        Please make sure to have elementtree installed (See below for
        the dependencies).
          
        Dependencies
        ============
        
        Required Products
        ------------------
        
        * Tested with Python 2.4.x, but should work with earlier and newer versions of Python
        
        * ElementTree library for Python is needed for Crunchy Frog tutorials in the "docs" folder
        
          http://effbot.org/zone/element-index.htm
        
        * Selenium RC 0.9.1 (selenium-remote-control-0.9.1-SNAPSHOT.zip 27-Dec-2006 01:49  8.8M):
        
          http://release.openqa.org/selenium-remote-control/nightly/
        
        * JRE (Java Runtime Environment) version 1.5 or higher is needed in order
          to run Selenium RC.
          
        * Firefox 2.x
        
        Installation
        ============
          
        Installing Funittest
        --------------------
        
        * Make it available in your Python module path or copy it to the
          Lib/site-packages folder
        
        --
        
        Experience is what you get when you were expecting something else.
        
Keywords: functional test framework
Platform: UNKNOWN
Classifier: Framework :: Zope2
Classifier: Framework :: Zope3
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Testing
Classifier: Topic :: Software Development :: Libraries :: Python Modules
