prego3


Nameprego3 JSON
Version 0.20210223 PyPI version JSON
download
home_pagehttps://github.com/davidvilla/prego
SummarySystem test framework for POSIX shells (python3 version)
upload_time2021-02-23 17:59:21
maintainer
docs_urlNone
authorDavid Villa Alises
requires_python
licenseGPLv3
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ### System test framework with Python

[![PyPI version](https://badge.fury.io/py/prego3.svg)](https://badge.fury.io/py/prego3) ![](https://github.com/davidvilla/prego3/workflows/test/badge.svg)

Prego is a library consisting on a set of clases and hamcrest matchers usefull
to specify shell command interactions through files, environment variables,
network ports. It provides support to run shell commands on background, send
signal to processes, set assertions on command stdout or stderr, etc.


### Subjects


A summary of subjects and their associated assertions.

#### ``Task(desc='', detach=False)``

Usuallys involve the execution of a program, pre-conditions and post-conditions as assertions.

Common assertions:

- ``assert_that``, for single shot checking.
- ``wait_that``, for polling recurrent checking.
- ``command``, to run arbitrary shell command.

Specific assertions:

- ``running()``, the task is still running.
- ``terminated()``, the task is over.


##### ``Task.command(cmd_line, stdout, stderr, expected, timeout, signal, cwd, env)``

Checks program execution.

Arguments:

- ``expected``: check command line return code. Assertion fails if value does not match.

  - Default value: 0.
  - Return code is ignored if is set to None.

- ``timeout``: assertion fails if execution time exceed timeout (in seconds)

  - Default value is 5.
  - With 0, timeout is not checked.

- ``signal``: send the given signal number to kill command.
- ``cwd``: change to the specified directory before execute command.
- ``env``: a diccionary of environment variables.

Assertions:

- ``running()``
- ``exits_with(value)``
- ``killed_by(signal)``


#### ``File(path)``

Check local files.

- ``exists()``: the file ``path`` exists.


#### ``File().content``

Checks contents of files.

- any hamcrest string matchers (ie: contains_string)

  - example: ``task.wait_that(File('foo'), hamcrest.is_(File('bar'))``


#### ``Variable(nam)``

Checks environment variables.

- ``exists()``: the variable ``name`` exists.
- any hamcrest string matchers (ie: contains_string)

  - example: ``task.assert_that(Variable(SHELL), hamcrest.constains_string('bash'))``



#### ``Host(hostname)``

Checks a network computer.

- ``listen_port(number, proto='tcp')``: a server is listen at ``port``.
- ``reachable()``: host answer to ping.


#### ``Package(name)``

Checks a Debian package

- ``installed()``


### context

The ``context`` is an object whose attributes may be automatically interpolated in command
and filename paths.

Some of them are set as default values for command() parameters too. If ``context.cwd`` is
set, all commands in the same test method will use that value as CWD (Current Working
Directory) unless you define a different value as ``command()`` keyarg.

Context attributes that defaults command() parameters are ``cwd``, ``timeout``,
``signal`` and ``expected``.


### Interpolation

Available interpolation variables are:

- ``$basedir``: the directory where prego is executed (relative).
- ``$fullbasedir``: absolute path of $basedir.
- ``$testdir``: the directory where the running test file is.
- ``$fulltestdir``: absolute path of $testdir.
- ``$testfilename``: the file name of the running test.
- ``$tmpbase``: a safe directory (per user) to put temporary files.
- ``$tmp``: a safe directory (per user and prego instance) to put temporary files.
- ``$pid``: the prego instance PID.


### Examples


#### Testing netcat

    import hamcrest
    from prego import Task, TestCase, context as ctx, running
    from prego.net import localhost, listen_port
    from prego.debian import Package, installed


    class Net(TestCase):
        def test_netcat(self):
            ctx.port = 2000
            server = Task(desc='netcat server', detach=True)
            server.assert_that(Package('nmap'), installed())
            server.assert_that(localhost,
                               hamcrest.is_not(listen_port(ctx.port)))
            cmd = server.command('ncat -l -p $port')
            server.assert_that(cmd.stdout.content,
                               hamcrest.contains_string('bye'))

            client = Task(desc='ncat client')
            client.wait_that(server, running())
            client.wait_that(localhost, listen_port(ctx.port))
            client.command('ncat -c "echo bye" localhost $port')


This test may be executed using nosetest::

    $ nosetests examples/netcat.py
    .
    ----------------------------------------------------------------------
    Ran 1 test in 1.414s

    OK


But prego provides a wrapper (the ``prego`` command) that has some interesting options:

    $ prego -h
    usage: prego [-h] [-c FILE] [-k] [-d] [-o] [-e] [-v] [-p] ...

    positional arguments:
      nose-args

    optional arguments:
      -h, --help            show this help message and exit
      -c FILE, --config FILE
                            explicit config file
      -k, --keep-going      continue even with failed assertion or tests
      -d, --dirty           do not remove generated files
      -o, --stdout          print tests stdout
      -e, --stderr          print tests stderr
      -v, --verbose         increase log verbosity


Same ncat test invoking ``prego``:

    [II] ------  Net.test_netcat BEGIN
    [II] [ ok ]   B.0 wait that A is running
    [II] [ ok ]   A.0 assert that nmap package is installed
    [II] [ ok ]   A.1 assert that localhost not port 2000/tcp to be open
    [II] [fail]   B.1 wait that localhost port 2000/tcp to be open
    [II] [ ok ]   B.1 wait that localhost port 2000/tcp to be open
    [II]          A.2.out| bye
    [II] [ ok ]   B.2 Command 'ncat -c "echo bye" localhost 2000' code (0:0) time 5:1.28
    [II] [ ok ]   B.3 assert that command B.2 returncode to be 0
    [II] [ ok ]   B.4 assert that command B.2 execution time to be a value less than <5>s
    [II] [ OK ]   B   Task end - elapsed: 1.17s
    [II] [ ok ]   A.2 Command 'ncat -l -p 2000' code (0:0) time 5:1.33
    [II] [ ok ]   A.3 assert that command A.2 returncode to be 0
    [II] [ ok ]   A.4 assert that command A.2 execution time to be a value less than <5>s
    [II] [ ok ]   A.5 assert that File '/tmp/prego-david/26245/A.2.out' content a string containing 'bye'
    [II] [ OK ]   A   Task end - elapsed: 1.32s
    [II] [ OK ]  Net.test_netcat END
    ----------------------------------------------------------------------
    Ran 1 test in 1.396s

    OK


#### Testing google reachability

    import hamcrest
    from prego import TestCase, Task
    from prego.net import Host, reachable

    class GoogleTest(TestCase):
        def test_is_reachable(self):
            link = Task(desc="Is interface link up?")
            link.command('ip link | grep wlan0 | grep "state UP"')

            router = Task(desc="Is the local router reachable?")
            router.command("ping -c2 $(ip route | grep ^default | cut -d' ' -f 3)")

            for line in file('/etc/resolv.conf'):
                if line.startswith('nameserver'):
                    server = line.split()[1]
                    test = Task(desc="Is DNS server {0} reachable?".format(server))
                    test.command('ping -c 2 {0}'.format(server))

            resolve = Task(desc="may google name be resolved?")
            resolve.command('host www.google.com')

            ping = Task(desc="Is google reachable?")
            ping.command('ping -c 1 www.google.com')
            ping.assert_that(Host('www.google.com'), reachable())
            ping.assert_that(Host('www.googlewrong.com'), hamcrest.is_not(reachable()))

            web = Task(desc="get index.html")
            cmd = web.command('wget http://www.google.com/webhp?hl=en -O-')
            web.assert_that(cmd.stdout.content,
                            hamcrest.contains_string('value="I\'m Feeling Lucky"'))
            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/davidvilla/prego",
    "name": "prego3",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "",
    "author": "David Villa Alises",
    "author_email": "David.Villa@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/14/bb/6279a06d132251855c2ebe4fce2659aa615e835e5cbbbfc250cc70780360/prego3-0.20210223.tar.gz",
    "platform": "",
    "description": "### System test framework with Python\n\n[![PyPI version](https://badge.fury.io/py/prego3.svg)](https://badge.fury.io/py/prego3) ![](https://github.com/davidvilla/prego3/workflows/test/badge.svg)\n\nPrego is a library consisting on a set of clases and hamcrest matchers usefull\nto specify shell command interactions through files, environment variables,\nnetwork ports. It provides support to run shell commands on background, send\nsignal to processes, set assertions on command stdout or stderr, etc.\n\n\n### Subjects\n\n\nA summary of subjects and their associated assertions.\n\n#### ``Task(desc='', detach=False)``\n\nUsuallys involve the execution of a program, pre-conditions and post-conditions as assertions.\n\nCommon assertions:\n\n- ``assert_that``, for single shot checking.\n- ``wait_that``, for polling recurrent checking.\n- ``command``, to run arbitrary shell command.\n\nSpecific assertions:\n\n- ``running()``, the task is still running.\n- ``terminated()``, the task is over.\n\n\n##### ``Task.command(cmd_line, stdout, stderr, expected, timeout, signal, cwd, env)``\n\nChecks program execution.\n\nArguments:\n\n- ``expected``: check command line return code. Assertion fails if value does not match.\n\n  - Default value: 0.\n  - Return code is ignored if is set to None.\n\n- ``timeout``: assertion fails if execution time exceed timeout (in seconds)\n\n  - Default value is 5.\n  - With 0, timeout is not checked.\n\n- ``signal``: send the given signal number to kill command.\n- ``cwd``: change to the specified directory before execute command.\n- ``env``: a diccionary of environment variables.\n\nAssertions:\n\n- ``running()``\n- ``exits_with(value)``\n- ``killed_by(signal)``\n\n\n#### ``File(path)``\n\nCheck local files.\n\n- ``exists()``: the file ``path`` exists.\n\n\n#### ``File().content``\n\nChecks contents of files.\n\n- any hamcrest string matchers (ie: contains_string)\n\n  - example: ``task.wait_that(File('foo'), hamcrest.is_(File('bar'))``\n\n\n#### ``Variable(nam)``\n\nChecks environment variables.\n\n- ``exists()``: the variable ``name`` exists.\n- any hamcrest string matchers (ie: contains_string)\n\n  - example: ``task.assert_that(Variable(SHELL), hamcrest.constains_string('bash'))``\n\n\n\n#### ``Host(hostname)``\n\nChecks a network computer.\n\n- ``listen_port(number, proto='tcp')``: a server is listen at ``port``.\n- ``reachable()``: host answer to ping.\n\n\n#### ``Package(name)``\n\nChecks a Debian package\n\n- ``installed()``\n\n\n### context\n\nThe ``context`` is an object whose attributes may be automatically interpolated in command\nand filename paths.\n\nSome of them are set as default values for command() parameters too. If ``context.cwd`` is\nset, all commands in the same test method will use that value as CWD (Current Working\nDirectory) unless you define a different value as ``command()`` keyarg.\n\nContext attributes that defaults command() parameters are ``cwd``, ``timeout``,\n``signal`` and ``expected``.\n\n\n### Interpolation\n\nAvailable interpolation variables are:\n\n- ``$basedir``: the directory where prego is executed (relative).\n- ``$fullbasedir``: absolute path of $basedir.\n- ``$testdir``: the directory where the running test file is.\n- ``$fulltestdir``: absolute path of $testdir.\n- ``$testfilename``: the file name of the running test.\n- ``$tmpbase``: a safe directory (per user) to put temporary files.\n- ``$tmp``: a safe directory (per user and prego instance) to put temporary files.\n- ``$pid``: the prego instance PID.\n\n\n### Examples\n\n\n#### Testing netcat\n\n    import hamcrest\n    from prego import Task, TestCase, context as ctx, running\n    from prego.net import localhost, listen_port\n    from prego.debian import Package, installed\n\n\n    class Net(TestCase):\n        def test_netcat(self):\n            ctx.port = 2000\n            server = Task(desc='netcat server', detach=True)\n            server.assert_that(Package('nmap'), installed())\n            server.assert_that(localhost,\n                               hamcrest.is_not(listen_port(ctx.port)))\n            cmd = server.command('ncat -l -p $port')\n            server.assert_that(cmd.stdout.content,\n                               hamcrest.contains_string('bye'))\n\n            client = Task(desc='ncat client')\n            client.wait_that(server, running())\n            client.wait_that(localhost, listen_port(ctx.port))\n            client.command('ncat -c \"echo bye\" localhost $port')\n\n\nThis test may be executed using nosetest::\n\n    $ nosetests examples/netcat.py\n    .\n    ----------------------------------------------------------------------\n    Ran 1 test in 1.414s\n\n    OK\n\n\nBut prego provides a wrapper (the ``prego`` command) that has some interesting options:\n\n    $ prego -h\n    usage: prego [-h] [-c FILE] [-k] [-d] [-o] [-e] [-v] [-p] ...\n\n    positional arguments:\n      nose-args\n\n    optional arguments:\n      -h, --help            show this help message and exit\n      -c FILE, --config FILE\n                            explicit config file\n      -k, --keep-going      continue even with failed assertion or tests\n      -d, --dirty           do not remove generated files\n      -o, --stdout          print tests stdout\n      -e, --stderr          print tests stderr\n      -v, --verbose         increase log verbosity\n\n\nSame ncat test invoking ``prego``:\n\n    [II] ------  Net.test_netcat BEGIN\n    [II] [ ok ]   B.0 wait that A is running\n    [II] [ ok ]   A.0 assert that nmap package is installed\n    [II] [ ok ]   A.1 assert that localhost not port 2000/tcp to be open\n    [II] [fail]   B.1 wait that localhost port 2000/tcp to be open\n    [II] [ ok ]   B.1 wait that localhost port 2000/tcp to be open\n    [II]          A.2.out| bye\n    [II] [ ok ]   B.2 Command 'ncat -c \"echo bye\" localhost 2000' code (0:0) time 5:1.28\n    [II] [ ok ]   B.3 assert that command B.2 returncode to be 0\n    [II] [ ok ]   B.4 assert that command B.2 execution time to be a value less than <5>s\n    [II] [ OK ]   B   Task end - elapsed: 1.17s\n    [II] [ ok ]   A.2 Command 'ncat -l -p 2000' code (0:0) time 5:1.33\n    [II] [ ok ]   A.3 assert that command A.2 returncode to be 0\n    [II] [ ok ]   A.4 assert that command A.2 execution time to be a value less than <5>s\n    [II] [ ok ]   A.5 assert that File '/tmp/prego-david/26245/A.2.out' content a string containing 'bye'\n    [II] [ OK ]   A   Task end - elapsed: 1.32s\n    [II] [ OK ]  Net.test_netcat END\n    ----------------------------------------------------------------------\n    Ran 1 test in 1.396s\n\n    OK\n\n\n#### Testing google reachability\n\n    import hamcrest\n    from prego import TestCase, Task\n    from prego.net import Host, reachable\n\n    class GoogleTest(TestCase):\n        def test_is_reachable(self):\n            link = Task(desc=\"Is interface link up?\")\n            link.command('ip link | grep wlan0 | grep \"state UP\"')\n\n            router = Task(desc=\"Is the local router reachable?\")\n            router.command(\"ping -c2 $(ip route | grep ^default | cut -d' ' -f 3)\")\n\n            for line in file('/etc/resolv.conf'):\n                if line.startswith('nameserver'):\n                    server = line.split()[1]\n                    test = Task(desc=\"Is DNS server {0} reachable?\".format(server))\n                    test.command('ping -c 2 {0}'.format(server))\n\n            resolve = Task(desc=\"may google name be resolved?\")\n            resolve.command('host www.google.com')\n\n            ping = Task(desc=\"Is google reachable?\")\n            ping.command('ping -c 1 www.google.com')\n            ping.assert_that(Host('www.google.com'), reachable())\n            ping.assert_that(Host('www.googlewrong.com'), hamcrest.is_not(reachable()))\n\n            web = Task(desc=\"get index.html\")\n            cmd = web.command('wget http://www.google.com/webhp?hl=en -O-')\n            web.assert_that(cmd.stdout.content,\n                            hamcrest.contains_string('value=\"I\\'m Feeling Lucky\"'))",
    "bugtrack_url": null,
    "license": "GPLv3",
    "summary": "System test framework for POSIX shells (python3 version)",
    "version": "0.20210223",
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "c1037a249ce4ff2cdf0cea961e4accf9",
                "sha256": "697b6c3380c84599df96fc8cf9057322933cbe68e40b28eff7ec3dade76be624"
            },
            "downloads": -1,
            "filename": "prego3-0.20210223.tar.gz",
            "has_sig": false,
            "md5_digest": "c1037a249ce4ff2cdf0cea961e4accf9",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 27192,
            "upload_time": "2021-02-23T17:59:21",
            "upload_time_iso_8601": "2021-02-23T17:59:21.068115Z",
            "url": "https://files.pythonhosted.org/packages/14/bb/6279a06d132251855c2ebe4fce2659aa615e835e5cbbbfc250cc70780360/prego3-0.20210223.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2021-02-23 17:59:21",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "github_user": null,
    "github_project": "davidvilla",
    "error": "Could not fetch GitHub repository",
    "lcname": "prego3"
}
        
Elapsed time: 0.25804s