Testplan, a multi-testing framework, because unit tests can only go so far.. http://testplan.readthedocs.io
Find a file
2024-05-02 15:27:17 +08:00
.github Add OpenSSF Scorecard analysis 2024-04-30 07:42:01 -04:00
dco Add cpages dco 2020-05-27 10:27:55 +08:00
doc Refactor/put certain report entries under SYNTHESIZED category (#1053) 2024-04-29 18:20:20 +08:00
examples Added error_handler hook to MultiTest (#1050) 2024-04-26 09:11:30 +02:00
releaseherald limit pydantic <2.0 (#969) 2023-07-04 17:38:36 +02:00
scripts Remove compatibility related code since no need to support Python 2 2021-04-30 14:26:51 +08:00
testplan Fix/wrong report category type (#1079) 2024-05-02 15:27:17 +08:00
tests Fix/wrong report category type (#1079) 2024-05-02 15:27:17 +08:00
.dockerignore Added dockerfile runtime support 2018-03-26 12:29:57 +01:00
.gitattributes Disable EXTEND_ESLINT 2020-10-22 13:47:28 +08:00
.gitignore Doit taskrunner (#905) 2023-03-06 17:57:44 +01:00
.readthedocs.yaml update rtd config to latest style (#1025) 2023-11-15 15:44:35 +01:00
CODEOWNERS Update CODEOWNERS (#1065) 2024-03-19 12:46:08 +01:00
CONTRIBUTING.rst Testplan testing framework. 2018-03-16 17:50:54 +00:00
dodo.py Doit taskrunner (#905) 2023-03-06 17:57:44 +01:00
install-testplan-ui Migrate to pnpm (#763) 2022-02-17 11:45:35 +01:00
LICENSE.md Updating license to make compatible with github auto detect 2018-03-21 21:55:05 +00:00
NOTICE.rst Remove executable bit from non-executable files 2020-01-24 14:47:51 +00:00
PULL_REQUEST_TEMPLATE.md Ignored fields (#728) 2021-11-24 16:55:35 +08:00
pylintrc Doit taskrunner (#905) 2023-03-06 17:57:44 +01:00
pyproject.toml Testplan BDD support. (#1071) 2024-04-09 10:24:16 +02:00
pytest.ini Use flask-restx to replace flask-restplus (#767) 2022-02-23 14:46:42 +08:00
README.rst Doit taskrunner (#905) 2023-03-06 17:57:44 +01:00
requirements-basic.txt Failed setup runtime status fix (#982) 2023-08-14 13:37:16 +02:00
requirements-build.txt Doit taskrunner (#905) 2023-03-06 17:57:44 +01:00
requirements-rtd.txt update rtd requirements (#1026) 2023-11-16 09:11:03 +01:00
requirements.txt Relax pandas version. (#1035) 2023-12-28 08:55:33 +01:00

|ReadTheDocs|_ |TravisCI|_

.. image:: https://badgen.net/badge/Lifecycle/Active/green
    :alt: Lifecycle Active

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
    :target: https://github.com/psf/black

.. image:: https://github.com/morganstanley/testplan/blob/main/doc/images/logo/testplan.png

a multi-testing framework
-------------------------

*..because unit tests can only go so far..*

Testplan is a `Python <http://python.org>`_ package that can start a local live
environment, setup mocks, connections to services and run tests against these.
It provides:

  * ``MultiTest`` a feature extensive functional testing system with a rich set
    of *assertions* and report rendering logic.
  * Built-in inheritable drivers to create a local live *environment*.
  * Configurable, diverse and expandable test execution mechanism including
    *parallel* execution capability.
  * Test *tagging* for flexible filtering and selective execution as well as
    generation of multiple reports (for each tag combination).
  * Integration with other unit testing frameworks (like GTest).
  * Rich, unified reports (json/PDF/XML) and soon (HTML/UI).


Basic example
=============

This is how a very basic Testplan application looks like.

.. code-block:: python

    import sys

    from testplan import test_plan
    from testplan.testing.multitest import MultiTest, testcase, testsuite

    def multiply(numA, numB):
        return numA * numB


    @testsuite
    class BasicSuite(object):

        @testcase
        def basic_multiply(self, env, result):
            result.equal(multiply(2, 3), 6, description='Passing assertion')
            result.equal(multiply(2, 2), 5, description='Failing assertion')


    @test_plan(name='Multiply')
    def main(plan):
        test = MultiTest(name='MultiplyTest',
                         suites=[BasicSuite()])
        plan.add(test)


    if __name__ == '__main__':
      sys.exit(not main())


Example execution:

.. code-block:: bash

    $ python ./test_plan.py -v
            Passing assertion - Pass
              6 == 6
            Failing assertion - Fail
              File: .../test_plan.py
              Line: 18
              4 == 5
          [basic_multiply] -> Fail
        [BasicSuite] -> Fail
      [MultiplyTest] -> Fail
    [Multiply] -> Fail


System integration testing example
==================================

Testing a server and a client communication.

.. code-block:: python

    import sys

    from testplan import test_plan
    from testplan.testing.multitest import MultiTest, testsuite, testcase
    from testplan.testing.multitest.driver.tcp import TCPServer, TCPClient
    from testplan.common.utils.context import context


    @testsuite
    class TCPTestsuite(object):
        """Testsuite for server client connection testcases."""

        def setup(self, env):
            env.server.accept_connection()

        @testcase
        def send_and_receive_msg(self, env, result):
            """Basic send and receive hello message testcase."""
            msg = env.client.cfg.name
            result.log('Client is sending his name: {}'.format(msg))
            bytes_sent = env.client.send_text(msg)

            received = env.server.receive_text(size=bytes_sent)
            result.equal(received, msg, 'Server received client name')

            response = 'Hello {}'.format(received)
            result.log('Server is responding: {}'.format(response))
            bytes_sent = env.server.send_text(response)

            received = env.client.receive_text(size=bytes_sent)
            result.equal(received, response, 'Client received response')


    @test_plan(name='TCPConnections')
    def main(plan):
        test = MultiTest(name='TCPConnectionsTest',
                         suites=[TCPTestsuite()],
                         environment=[
                             TCPServer(name='server'),
                             TCPClient(name='client',
                                       host=context('server', '{{host}}'),
                                       port=context('server', '{{port}}'))])
        plan.add(test)


    if __name__ == '__main__':
        sys.exit(not main())


Example execution:

.. code-block:: bash

    $ python ./test_plan.py -v
            Client is sending: client
            Server received - Pass
              client == client
            Server is responding: Hello client
            Client received - Pass
              Hello client == Hello client
          [send_and_receive_msg] -> Pass
        [TCPTestsuite] -> Pass
      [TCPConnectionsTest] -> Pass
    [TCPConnections] -> Pass

A persistent and human readable test evidence PDF report:

.. code-block:: bash

    $ python ./test_plan.py --pdf report.pdf
      [TCPConnectionsTest] -> Pass
    [TCPConnections] -> Pass
    PDF generated at report.pdf

.. image:: https://github.com/morganstanley/testplan/blob/main/doc/images/pdf/readme_server_client.png


Documentation
=============

For complete documentation that includes downloadable examples, visit this
`link <http://testplan.readthedocs.io>`_.


Contribution
============

A step by step guide to contribute to Testplan framework can be found
`here <http://testplan.readthedocs.io/en/latest/about.html#contributing>`_.


License
=======

License information `here <https://github.com/morganstanley/testplan/blob/main/LICENSE.md>`_.

.. |ReadTheDocs| image:: https://readthedocs.org/projects/testplan/badge/?version=latest
.. _ReadTheDocs: http://testplan.readthedocs.io/en/latest/
.. |TravisCI| image:: https://api.travis-ci.com/MorganStanley/testplan.svg?branch=main
.. _TravisCI: https://travis-ci.com/morganstanley/testplan