Turn your manual testers into automation experts Request a DemoStart testRigor Free

CherryPy Testing

CherryPy Testing

CherryPy is a minimalist, open-source web framework for building web applications using the Python programming language. It was first released in 2002 and is designed to be simple, lightweight, and easy to use, providing a clean and straightforward interface for developing web applications.

CherryPy allows developers to build web applications in a similar way they would build any other Python application, using object-oriented programming concepts and structures. It handles the underlying HTTP protocol, enabling developers to focus on writing the logic of their applications without worrying about low-level details.

Some of the key features of CherryPy include:
  • An HTTP server: CherryPy includes a built-in, high-performance HTTP server, making it easy to deploy and serve web applications without the need for an external web server.
  • A clean architecture: CherryPy uses a simple and clean architecture that promotes a clear separation of concerns, making it easier to maintain and extend your applications.
  • Easy configuration: CherryPy allows you to easily configure your application using Python code, environment variables, or configuration files.
  • Extensibility: CherryPy can be easily extended with custom plugins and middleware to add additional functionality to your applications.
  • Cross-platform compatibility: CherryPy works on multiple platforms, including Windows, macOS, and Linux, providing a consistent development experience across different operating systems.

While CherryPy may not be as feature-rich as some other web frameworks like Django or Flask, its simplicity and minimalism make it a popular choice for developers who prefer a more lightweight approach to web development in Python.

You can test applications built using CherryPy in the following ways:

Unit Testing

Unit testing forms the base of the testing pyramid. It is a software testing technique that involves testing individual components or units of a software application to ensure that they function as expected. A unit is the smallest testable part of the software, usually a single function, method, or class, depending on the programming language used.

The primary goal of unit testing is to verify that each unit of the software performs its intended task correctly and to identify any potential issues, bugs, or defects early in the development process.

CherryPy offers a helper module while also integrating with other testing tools. Let's take a look at them.

Testing using CherryPy helper module (cherrypy.test)

The cherrypy.test package contains modules and classes used for testing and debugging CherryPy applications. The helper module, in particular, provides a set of helper classes that make it easier to write tests for CherryPy applications. By importing the helper module, the code can make use of the testing utilities provided by CherryPy, such as CPWebCase, which is a subclass of unittest.TestCase, that provides additional functionality for testing CherryPy applications. The helper module inherits from the Unittest.TestCase class.

Below is an example of a unit test using the helper class. The test case sets up a CherryPy server with a simple Root class that defines an echo method that returns the message parameter passed in the query string. The test case then sends a GET request to the /echo endpoint with the message parameter set to "Hello world" and verifies that the server returns a 200 OK response with the correct message in the body. The second test case sends a similar request, but with a non-UTF8 encoded message, which should result in a 404 Not Found response.

import cherrypy
from cherrypy.test import helper

class SimpleCPTest(helper.CPWebCase):
  def setup_server():
    class Root(object):
      @cherrypy.expose
      def echo(self, message):
        return message
    
    cherrypy.tree.mount(Root())
  setup_server = staticmethod(setup_server)
  
  def test_message_should_be_returned_as_is(self):
    self.getPage("/echo?message=Hello%20world")
    self.assertStatus('200 OK')
    self.assertHeader('Content-Type', 'text/html;charset=utf-8')
    self.assertBody('Hello world')
  
  def test_non_utf8_message_will_fail(self):
    siders it's a different URL.
      """
      self.getPage("/echo?message=A+bient%F4t",
        headers=[
          ('Accept-Charset', 'ISO-8859-1,utf-8'),
          ('Content-Type', 'text/html;charset=ISO-8859-1')
        ]
      )
      self.assertStatus('404 Not Found')

Using Unittest for testing

Unittest is the standard library offered by Python for testing Python code. CherryPy is compatible with this library. In fact, the above-mentioned helper module is based on Unittest. You simply need to import Unittest into your test case and then continue writing the test methods as you would write in any other Python framework that is compatible with Unittest.

Using Pytest for testing

You can use Pytest to test your CherryPy code. Pytest is a popular third-party testing framework in Python that supports writing unit test cases. Not just that, it also has a simple and easy-to-learn syntax and provides many features for testing, including fixtures, parameterization, and test discovery.

Integration Testing

When it comes to web applications, it is vital to verify if different modules or components are working harmoniously. To do so, you need to write tests that check such integrations. Integrations between different joints become the focus, such as methods interacting with other methods, APIs, services, helpers, UI components, databases, network systems, or middleware.

Like unit testing, integration tests use the same libraries and tools. They are as below.

Using CherryPy helper module (cherrypy.test)

You can use CherryPy's helper module to write integration tests. It provides a full-stack HTTP test client that can interact with CherryPy servers programmatically and can test not just CherryPy code but also other WSGI-compliant web frameworks.

Here is an example of an integration test where the application is running in a simulated environment using the CPWebCase helper class from the cherrypy.test module. The test case sets up a simple CherryPy application that defines an /echo endpoint that accepts a msg parameter and returns it as the response body. It also has two test methods test_message and test_non_utf8_message_will_fail.

import cherrypy
from cherrypy.test import helper

class HelperSubclass(helper.CPWebCase):
  def setup_s():
    class Root(object):
      @cherrypy.expose	
      def echo(self, msg):
        return msg
    
    cherrypy.tree.mount(Root())
  setup_s = staticmethod(setup_s)
  
  def test_message(self):
    ''' This is a test method'''
    self.getPage("/echo?message=Hello%20Ninja")
    self.assertStatus('200 OK')
    self.assertHeader('Content-Type', 'text/html;charset=utf-8')
    self.assertBody('Hello Ninja')
  
  def test_non_utf8_message_will_fail(self):
    self.getPage("/echo?msg=A+bient%F4t",
      headers=[
        ('Accept-Charset',  'ISO-8859-1, utf-8'),
        ('Content-Type',  'text/html; charset=ISO-8859-1')
      ]
    )
  self.assertStatus('404 Not Found')

Using Nose and Webtest for testing

Nose and Webtest are Python libraries that are used for writing tests in Python-based frameworks. Nose is a third-party testing tool built on top of Unittest. It provides additional features like test discovery, test grouping, and plugin support. It also has a more user-friendly output than the built-in Unittest framework. Webtest is a third-party library that allows you to test web applications by making HTTP requests and examining the responses. It provides a simple and intuitive interface for creating requests and inspecting responses. You can also integrate with Unittest and Pytest to compose better test cases.

Here is an example of a test that tests the default authentication setup for a web application. The test ensures that anonymous users are forced to log in when trying to access a protected area of the application. It does this by sending a request to a protected application area and checking that the response status code is 302 (redirect). The test then follows the redirect to the login form and submits a valid form. Finally, it checks that the user is redirected to the initially requested page and that a session cookie is set.

from webtest import TestApp
from nose.tools import eq_

class TestAuthentication(object):
	
  application_under_test = 'main'
  
  def setUp(self):
    # Loading the application:
    conf_dir = config.here
    wsgiapp = loadapp('config:test.ini#%s' % self.application_under_test,
      relative_to=conf_dir)
    self.app = TestApp(wsgiapp)
    
    # Setting it up:
    test_file = path.join(conf_dir, 'test.ini')
    cmd = SetupCommand('setup-app')
    cmd.run([test_file])
  
  def tearDown(self):
    # Cleaning up the database:
    model.DBSession.remove()
    teardown_db()
  
  def test_forced_login(self):
    # Requesting a protected area
    resp = self.app.get('/secc/', status=302)
    assert resp.location.startswith('http://localhost/login')
    
    # Getting the login form:
    resp = resp.follow(status=200)
    print resp.forms
    form = resp.forms
    
    # Submitting the login form:
    form['login'] = u'manager'
    form['password'] = 'managepass'
    post_login = form.submit(status=302)
    
    # Being redirected to the initially requested page:
    assert post_login.location.startswith('http://localhost/post_login')
    initial_page = post_login.follow(status=302)
    assert 'authtkt' in initial_page.request.cookies, \
      "Session cookie wasn't defined: %s" % initial_page.request.cookies
    assert initial_page.location.startswith('http://localhost/secc/'), \
      initial_page.location

Using Pytest and Unittest

You can use Pytest and Unittest as well for writing integration tests. The test format, as well as the use of those tools remains the same. The only aspect you need to consider is how to compose your integration tests so that appropriate integrations are checked.

When it comes to choosing from these libraries/tools, you can decide which tool or tools to use based on your team's experience and preference, project requirements, and community support offered for that tool. All of the above-mentioned tools are compatible with Python, but if you are looking for a built-in solution provided by CherryPy, then cherrypy.test is the best choice.

End-to-End Testing

Up until now, our focus has been on whether the methods produced the desired outcomes and whether they effectively interacted with other components and modules within the application. In other words, we were concentrating on the code. Now, let's turn our attention to the end user. Such a user isn't concerned with the underlying mechanics, but rather, how the system assists them in achieving their goals. With end-to-end tests, the emphasis shifts to the user's interaction with the system and whether the system, in turn, is helping them accomplish their business objectives. These test cases can also be automated.

The most common tools to assist with these type of testing are:
  • CherryPy's cherrypy.test helper module along with Selenium
  • testRigor

CherryPy's cherrypy.test helper module along with Selenium

You can write end-to-end test cases using cherrypy.test. However, when it comes to end-to-end tests, you need ways to test the client-side behavior of the application. This is where Selenium comes into the picture. Selenium WebDriver provides a set of APIs for automating browser interactions, such as clicking buttons, filling in forms, and verifying page content.

In the below example, we use Selenium WebDriver to automate the process of entering a search query and submitting the search form. We can verify that the web application behaves correctly from the user's perspective, that is, it responds to user input in the expected way and displays the expected content.

import cherrypy
from cherrypy.test import helper
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class SearchTest(helper.CPWebCase):
		
  @classmethod
  def setup_server(cls):
    class Root(object):
      @cherrypy.expose
      def index(self):
        return '''
        <html>
          <body>
            <form method="get" action="/search">
              <input type="text" name="q">
              <input type="submit" value="Search">
            </form>
          </body>
        </html>
        '''
      
      @cherrypy.expose
      def search(self, q=None):
      		return f"Search results for '{q}'"
    
    cherrypy.tree.mount(Root())
  
  def test_search(self):
    self.getPage("/")
    self.assertStatus('200 OK')
    self.assertHeader('Content-Type', 'text/html;charset=utf-8')
    
    # Simulate user typing a query into search box
    self.browser.get(self.getUrl("/"))
    input_box = self.browser.find_element_by_name("q")
    input_box.send_keys("cherry pie")
    input_box.send_keys(Keys.ENTER)
    
    # Verify that search results page is returned with the correct query
    self.assertStatus('200 OK')
    self.assertHeader('Content-Type', 'text/html;charset=utf-8')
    self.assertBody("Search results for 'cherry pie'")

if __name__ == '__main__':
  helper.testmain()

It is essential to mention that while Selenium is still a widely used option for automation testing, it is complex, slow to execute, and requires a vast amount of test maintenance. Which is why testRigor might be a more viable option for your company.

testRigor

When it comes to end-to-end testing, incorporating input from various team members, such as manual testers and business analysts who understand user scenarios, can significantly enhance the process. While it is possible to integrate collaboration-supporting tools like BDD tools, these can introduce overhead and still require coding test cases, which may be challenging for non-technical individuals to comprehend. As a more comprehensive solution, testRigor will streamline the process.

testRigor is a no-code, AI-driven, cloud-based platform for web, mobile, and desktop testing. Its scripts are written in plain English, eliminating the need for coding and making it more accessible for team members with varying levels of technical expertise. testRigor is renowned for its ease of test maintenance and is an ideal tool for end-to-end automation testing. It boasts features such as visual testing, API testing, referencing UI elements using relative locations (instead of Xpaths or other locators), generating test data, accessing databases, audio testing, and more. Additionally, testRigor supports integrations with most CI/CD frameworks, test case management systems, infrastructure, and databases.

The following example demonstrates a testRigor automated test case for a web application, showcasing simplicity and user-friendliness:
login 
check that page contains "Welcome Janet" at the top 
check if page contains "Search" 
enter "cherry pie" in "Search" 
enter enter
check that page contains "cherry pie" below "Here are your results"
click on "clear" to the right of "cherry pie"
enter enter
check that page does not contain "cherry pie" below "Here are your results"
check that page contains "Welcome Janet"

The main benefits of testRigor for end-to-end testing include a straightforward initial setup, ease and speed of test creation, robustness of tests, and virtually eliminated test maintenance.

Conclusion

In conclusion, CherryPy is a lightweight and minimalist web framework for Python that allows developers to build web applications with ease. It offers a range of testing options, from unit testing to integration and end-to-end testing, ensuring the functionality and reliability of applications. CherryPy provides its own helper module for testing and supports third-party libraries such as Unittest, Pytest, Nose, and Webtest, making it compatible with various testing tools.

For end-to-end testing, you can use CherryPy's helper module in conjunction with Selenium or opt for testRigor, a no-code, AI-driven testing platform that simplifies the process and allows for greater collaboration among team members. With a variety of testing tools and techniques available, CherryPy enables developers to create and maintain high-quality web applications that meet both technical and user requirements.