Tools for unit testing

Fixture overview

' Copyright 2017, 2018 Reahl Software Services (Pty) Ltd. All rights reserved.

@startuml
!include base.iuml
show members
skinparam class{
 BorderColor Black
}

title Fixtures

package reahl-dev{
	class ContextAwareFixture {
	}

	class ReahlSystemSessionFixture <<session-scoped>> {
	    context
	    config
	    reahl_system
	    system_control
	}

	class ReahlSystemFixture {
	    context
	    @system_control
	    config
	}
}

package reahl-sqlalchemysupport{
	class SqlAlchemyFixture {
	    persistent_test_classes
	    start_transaction()
	    finalise_transaction()
	}
}

package reahl-webdev{
	class WebServerFixture <<session-scoped>> {
	    reahl_server
	    web_driver
	    driver_browser
	    firefox_driver
	    chrome_driver
	}
}

package reahl-web_dev{
	class WebFixture {
	      request
	      view
	      current_location
	      wsgi_app
	      user_interface
	      driver_browser
	      log_in()
	}
}

package reahl-domain_dev{
	class PartyAccountFixture {
	      session
	      party
	      system_account
	}
}


ContextAwareFixture <|-- ReahlSystemSessionFixture
ContextAwareFixture <|-- ReahlSystemFixture
ReahlSystemSessionFixture <-left- ReahlSystemFixture 

ReahlSystemFixture <-- SqlAlchemyFixture 
WebServerFixture -up-> ReahlSystemSessionFixture

ReahlSystemFixture <-- WebFixture
WebServerFixture <-- WebFixture
PartyAccountFixture <-- WebFixture


ReahlSystemFixture <-- PartyAccountFixture
SqlAlchemyFixture <-- PartyAccountFixture



@enduml

Basic fixtures

ContextAwareFixture

class reahl.dev.fixtures.ContextAwareFixture

A ContextAwareFixture is a Fixture which has an ExecutionContext as one of its elements.

Such a Fixture ensures that its setup and teardown actions are done within its .context, and that tests using it are also run within its .context.

ReahlSystemSessionFixture

class reahl.dev.fixtures.ReahlSystemSessionFixture

A session-scoped Fixture which sets up all the basics any Reahl system needs to run.

Upon set up, it creates a new empty database with the correct database schema for the project and sets up any persistent classes for use with that schema. It also connects to the database. Upon tear down, the Fixture disconnects from the database.

To be able to do all that, it needs to provide a basic ExecutionContext with the appropriate configuration, which it reads from the ‘etc’ directory relative to the current directory.

Note

You should not use this fixture directly in tests because changes to, eg. the ExecutionContext it provides will persist between different tests. The idea is for ReahlSystemSessionFixture to be used by other Fixtures that are not session scoped, but that uses this one where necessary. See for example ReahlSystemFixture.

new_config()

The main Configuration of the system.

This is read from disk from the ‘etc’ directory present in the current working directory where tests are run.

new_context(config=None, system_control=None)

The ExecutionContext within which all tests are run.

new_system_control()

The SystemControl with which you can control the underlying database.

ReahlSystemFixture

class reahl.dev.fixtures.ReahlSystemFixture

A Fixture for direct use in test which sets up all the basics any Reahl system needs to run.

ReahlSystemFixture does its work by using a ReahlSystemSessionFixture behind the scenes. ReahlSystemFixture provides copies of most of the session-scoped stuff in the ReahlSystemSessionFixture. This allows you to “inherit” the configuration set up for the session by default, but also allows you to change the configuration and ExecutionContext for a particular test, safe in the knowledge that such changes will be torn down after each test function ran.

Managing a SqlAlchemy database

SqlAlchemyFixture

class reahl.sqlalchemysupport_dev.fixtures.SqlAlchemyFixture

SqlAlchemyFixture ensures that a transaction is started before each test run, and rolled back after each test so as to leave the database unchanged between tests. It also contains a handy method persistent_test_classes() that can be used to add persistent classes to your database schema just for purposes of the current test.

persistent_test_classes(*entities)

A context manager that creates the tables needed for the entities passed to it, and which sets the necessary SqlAlchemy wiring up for thos entities to work. The tables are destroyed again after the context is exited.

This is useful for having persistent classes that may even need their own tables in the database but which should stay part of test code only, and are thus not listed in the <persisted> section of any egg.

Web development fixtures

WebServerFixture

class reahl.web_dev.fixtures.WebServerFixture

A Fixture to be used as session fixture. It sets up a running, configured web server before any test runs, and more than one flavour of a Selenium 2.x WebDriver. WebServerFixture also stops all the necessary servers upon tear down.

The web server started runs in the same thread as your tests, making debugging easier.

reahl_server

The reahl.webdev.webserver.ReahlWebServer for this test process.

firefox_driver

A WebDriver instance set up to work with the running reahl_server, via Firefox.

chrome_driver

A WebDriver instance set up to work with the running reahl_server, via Chrome. Note that this expects a Chrome binary to be present at /usr/lib/chromium-browser/chromium-browser

web_driver

The default WebDriver instance (Chrome, by default).

WebFixture

class reahl.web_dev.fixtures.WebFixture

A function-scoped Fixture for use when testing a website via selenium or to test things as if you are inside the server.

For example, it supplies a View for when you want to instantiate a Widget.

property context

The current ExecutionContext.

property config

The current Configuration.

new_request(path=None, url_scheme=None)

A Request for testing.

log_in(browser=None, session=None, system_account=None, stay_logged_in=False)

Logs the user into the current webapp without having to navigate to a login page.

new_driver_browser(driver=None)

A DriverBrowser instance for controlling the browser.

property chrome_driver

A selenium WebDriver instance for Chromium.

property firefox_driver

A selenium WebDriver instance for Firefox.

property web_driver

The default selenium WebDriver instance.

property reahl_server

The running Reahl webserver.

To use it, you will have to call set_app() to specify the WSGI application to serve.

new_wsgi_app(site_root=None, enable_js=False, config=None, child_factory=None)

Creates a ReahlWSGIApplication containing a UserInterface with a single View.

Parameters
  • site_root – an optional supplied UserInterface for the webapp

  • enable_js – If True, JS files will be served. The default is False, to save time.

  • config – A configuration to use.

  • child_factory – A Widget to include in the single-view site (only applicable if no site_root) is given.

property current_location

The current Url as displayed in the browser location bar.

new_view()

An UrlBoundView to use when constructing Widgets for testing.

new_user_interface()

A UserInterface for testing.

General web development tools

ReahlWebServer

class reahl.webdev.webserver.ReahlWebServer(config)

A web server for testing purposes. This web server runs both an HTTP and HTTPS server. It can be configured to handle requests in the same thread as the test itself, but it can also be run in a separate thread. The ReahlWebServer requires a certificate for use with HTTPS upon startup. A self signed certificate has been provided as part of the distribution for convenience.

Parameters

config – The reahl.component.config.Configuration instance to use as config for this process.

classmethod from_config_directory(directory)

Creates a new ReahlWebServer given a port and standard configuration directory for an application.

Parameters

directory – The directory from which configuration will be read.

..versionchanged:: 5.1

Removed port keyword argument, port and encrypted port will be set from the config found in the directory argument.

..versionchanged:: 5.1

Renamed from camel case name.

set_app(new_wsgi_app)

Changes the currently served application to new_wsgi_app.

start(in_separate_thread=True, connect=False)

Starts the webserver and web application.

Parameters
  • in_separate_thread – If False, the server handles requests in the same thread as your tests.

  • connect – If True, also connects to the database.

stop()

Stops the webserver and web application from running.

serve(timeout=0.01)

Call this method once to have the server handle all waiting requests in the calling thread.

install_handler(web_driver)

Installs this server’s request handler into the given web_driver. This enables the server to serve requests from the web_driver in the current thread.

in_background(wait_till_done_serving=True)

Returns a context manager. Within the context of this context manager, the webserver is temporarily run in a separate thread. After the context managed by this context manager is exited, the server reverts to handling requests in the current (test) thread.

Parameters

wait_till_done_serving – If True, wait for the server to finish its background job before exiting the context block.