Voip Open Linear Testing Suite

Related tags

Testingvolts
Overview

VOLTS

Voip Open Linear Tester Suite

Functional tests for VoIP systems based on voip_patrol and docker

10'000 ft. view

System is designed to run simple call scenarios, that you usually do with your desk phones. So, call some destination and control call arrival on another phone(s).
This tool would not configure your PBX to provide call flows, it's up to you. It will just make and receive calls, nothing more. It also will not do transfers at the moment. Sorry

Suite consists of 3 parts, that are running sequentially

  1. Preparation - at this part we're transforming templates to real scenarios using Jinja2 template engine
  2. Running voip_patrol against list of scenarios sequentially. One scenario at a time
  3. Report - at this part we're analyzing results of previous step reading and interpreting file obtained at step 2. Printing results in a desired way. Table by default.

Building

Suite is designed to run locally from your Linux PC or Mac. And of course, docker should be installed. It's up to you.
To build, just run ./build.sh. It would build 3 docker images and tag em accordingly.

Running

After building, just run

./run.sh

Simple, isn't it? This will run all scenarios found in vp_scenarios folder. To run single scenario, run

./run.sh <scenario_name>.xml

or

./run.sh vp_scenarios/<scenario_name>.xml

After running of the suite you can always find a voip_patrol presented results in tmp/output folder.

But simply run something blindly is boring, so before this best to do some

Configuration

We suppose to configure 2 parts here. First, and most complex are

Scenarios

VOLTS scenarios are voip_patrol scenarios, that are just being templatized with Jinja2 style. Mostly done not to repeat some passwords, usernames, domains, etc.
Values for templates are taken from vp_scenarios/config.yaml
One thing to mention here, that vars from global section transforms to c. and from accounts to a. in templates for shorter notation.
Also all settings from global section are inherited to accounts section automatically, unless they are defined there explicitly.
To get most of it, please refer to voip_patrol config, but here just some more basic examples.

config.yaml

global:
  domain:     '
   
    '
   
  transport:  'tls'
  srtp:       'dtls,sdes,force'
  play_file:  '/voice_ref_files/8000_12s.wav'
accounts:
  '88881':
    username: '88881'
    password: 'SuperSecretPass1'
  '88882':
    username: '88882'
    password: 'SuperSecretPass1'
  '90001':
    username: '90001'
    password: 'SuperSecretPass2'

Make a successful register

">
<config>
    <actions>
        <action type="register" label="Register {{ a.88881.label }}"
            transport="{{ a.88881.transport }}"
            account="{{ a.88881.label }}"
            username="{{ a.88881.username }}"
            password="{{ a.88881.password }}"
            registrar="{{ c.domain }}"
            realm="{{ a.88881.domain }}"
            expected_cause_code="200"
        />
        <action type="wait" complete="true" ms="2000"/>
    actions>
config>

Expect fail on register

">
<config>
    <actions>
        <action type="register" label="Register {{ a.88881.label }}"
            transport="{{ a.88881.transport }}"
            account="{{ a.88881.label }}"
            username="{{ a.88881.username }}"
            password="{{ a.88881.password }}"
            registrar="{{ c.domain }}"
            realm="{{ a.88881.domain }}"
            expected_cause_code="407"
        />
        <action type="wait" complete="true" ms="2000"/>
    actions>
config>

Register with 1 account and make a call

from 90001 to 88881. Max wait time to answer - 15 sec, duration of connected call - 10 sec.
Point, we don't register account 90001 here, as we're not receiving a calls on it, just need to provide credentials on INVITE.

">
<config>
    <actions>
        <action type="codec" disable="all"/>
        <action type="codec" enable="pcma" priority="250"/>
        <action type="codec" enable="pcmu" priority="249"/>
        <action type="codec" enable="opus" priority="248"/>
        <action type="register" label="Register {{ a.88881.label }}"
            transport="{{ a.88881.transport }}"
            account="{{ a.88881.label }}"
            username="{{ a.88881.username }}"
            password="{{ a.88881.password }}"
            registrar="{{ c.domain }}"
            realm="{{ c.domain }}"
            expected_cause_code="200"
            srtp="{{ a.88881.srtp }}"
        />
        <action type="wait" complete="true" ms="2000"/>
        <action type="accept" label="Receive call on {{ a.88881.label }}"
            call_count="1"
            account="{{ a.88881.label }}"
            hangup="10"
            code="200" reason="OK"
            transport="{{ a.88881.transport }}"
            srtp="{{ a.88881.srtp }}"
            play="{{ c.play_file }}"
        />
        <action type="call" label="Call {{ a.90001.label }} -> {{ a.88881.label }}"
            transport="tls"
            expected_cause_code="200"
            caller="{{ a.90001.label }}@{{ c.domain }}"
            callee="{{ a.88881.label }}@{{ c.domain }}"
            from="sip:{{ a.90001.label }}@{{ c.domain }}"
            to_uri="{{ a.88881.label }}@{{ c.domain }}"
            max_duration="20" hangup="10"
            username="{{ a.90001.username }}"
            password="{{ a.90001.password }}"
            realm="{{ c.domain }}"
            rtp_stats="true"
            max_ring_duration="15"
            srtp="{{ a.90001.srtp }}"
            play="{{ c.play_file }}"
        />
        <action type="wait" complete="true" ms="30000"/>
    actions>
config>

Register with 2 accounts

and call from third one, not answer on 1st and make sure we receive call on second. So, your PBX should be configured to make a Forward-No-Answer from 88881 to 88882

">
<config>
    <actions>
        <action type="codec" disable="all"/>
        <action type="codec" enable="pcma" priority="250"/>
        <action type="codec" enable="pcmu" priority="249"/>
        <action type="codec" enable="opus" priority="248"/>
        <action type="register" label="Register {{ a.88881.label }}"
            transport="{{ a.88881.transport }}"
            account="{{ a.88881.label }}"
            username="{{ a.88881.username }}"
            password="{{ a.88881.password }}"
            registrar="{{ c.domain }}"
            realm="{{ c.domain }}"
            expected_cause_code="200"
            srtp="{{ a.88881.srtp }}"
        />
        <action type="register" label="Register {{ a.88882.label }}"
            transport="{{ a.88882.transport }}"
            account="{{ a.88882.label }}"
            username="{{ a.88882.username }}"
            password="{{ a.88882.password }}"
            registrar="{{ c.domain }}"
            realm="{{ c.domain }}"
            expected_cause_code="200"
            srtp="{{ a.88882.srtp }}"
        />
        <action type="wait" complete="true" ms="2000"/>
        <action type="call" label="Call from 90001 to 88881->88882"
            transport="{{ a.90001.transport }}"
            expected_cause_code="200"
            caller="{{ a.90001.label }}@{{ c.domain }}"
            callee="88881@{{ c.domain }}"
            from="sip:{{ a.90001.label }}@{{ c.domain }}"
            to_uri="88881@{{ c.domain }}"
            max_duration="20" hangup="10"
            username="{{ a.90001.username }}"
            password="{{ a.90001.password }}"
            realm="{{ c.domain }}"
            rtp_stats="true"
            max_ring_duration="60"
            srtp="{{ a.90001.srtp }}"
            play="{{ c.play_file }}"
        />
        <action type="accept" label="Receive call on {{ a.88881.label }}"
            account="{{ a.88881.label }}"
            call_count="1"
            hangup="10"
            ring_duration="30"
            cancel="force"
            transport="{{ a.88881.transport }}"
            srtp="{{ a.88881.srtp }}"
        />
        <action type="accept" label="Receive call on {{ a.88882.label }}"
            account="{{ a.88882.label }}"
            call_count="1"
            hangup="10"
            code="200" reason="OK"
            transport="{{ a.88882.transport }}"
            srtp="{{ a.88882.srtp }}"
            play="{{ c.play_file }}"
        />
        <action type="wait" complete="true" ms="20000"/>
    actions>
config>

run.sh script

Not that much to configure here, mostly you'll be interested in setting environement variables at the start of the script

Variable name Description
REPORT_TYPE Actually, report type, that would be provided at the end.
table - print results in table, only failed tests are pritend.
json - print results in JSON format, only failed tests are pritend.
table_full, json_full - prints results in table or JSON respectively, but print full info on tests passed
VP_LOG_LEVEL voip_patrol log level on the console

Results

As a results, you would have tables like

+-------------------------+----------------+--------+-----------------+
|                Scenario |           Test | Status |            Text |
+-------------------------+----------------+--------+-----------------+
| 09-queue-forward-member |                |   PASS | Scenario passed |
|                         | Register 90002 |   PASS |     Test passed |
|                         |  Call to 91502 |   PASS |     Test passed |
+-------------------------+----------------+--------+-----------------+
Tests passed OK!

Not really much to describe here, just read info on the console

Owner
Igor Olhovskiy
VoIP engineer and developer. Asterisk/Freeswitch/Kamailio/OpenSIPS and all related to this stuff.
Igor Olhovskiy
Fi - A simple Python 3.9+ command-line application for managing Fidelity portfolios

fi fi is a simple Python 3.9+ command-line application for managing Fidelity por

Darik Harter 2 Feb 26, 2022
Declarative HTTP Testing for Python and anything else

Gabbi Release Notes Gabbi is a tool for running HTTP tests where requests and responses are represented in a declarative YAML-based form. The simplest

Chris Dent 139 Sep 21, 2022
A cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.

PyAutoGUI PyAutoGUI is a cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard. pip inst

Al Sweigart 7.5k Dec 31, 2022
HTTP traffic mocking and testing made easy in Python

pook Versatile, expressive and hackable utility library for HTTP traffic mocking and expectations made easy in Python. Heavily inspired by gock. To ge

Tom 305 Dec 23, 2022
Python scripts for a generic performance testing infrastructure using Locust.

TODOs Reference to published paper or online version of it loadtest_plotter.py: Cleanup and reading data from files ARS_simulation.py: Cleanup, docume

Juri Tomak 3 Dec 15, 2022
Pytest modified env

Pytest plugin to fail a test if it leaves modified os.environ afterwards.

wemake.services 7 Sep 11, 2022
Let your Python tests travel through time

FreezeGun: Let your Python tests travel through time FreezeGun is a library that allows your Python tests to travel through time by mocking the dateti

Steve Pulec 3.5k Dec 29, 2022
tidevice can be used to communicate with iPhone device

tidevice can be used to communicate with iPhone device

Alibaba 1.8k Jan 08, 2023
Show, Edit and Tell: A Framework for Editing Image Captions, CVPR 2020

Show, Edit and Tell: A Framework for Editing Image Captions | arXiv This contains the source code for Show, Edit and Tell: A Framework for Editing Ima

Fawaz Sammani 76 Nov 25, 2022
A small faсade for the standard python mocker library to make it user-friendly

unittest-mocker Inspired by the pytest-mock, but written from scratch for using with unittest and convenient tool - patch_class Installation pip insta

Vertliba V.V. 6 Jun 10, 2022
Turn any OpenAPI2/3 and Postman Collection file into an API server with mocking, transformations and validations.

Prism is a set of packages for API mocking and contract testing with OpenAPI v2 (formerly known as Swagger) and OpenAPI v3.x. Mock Servers: Life-like

Stoplight 3.3k Jan 05, 2023
UX Analytics & A/B Testing

UX Analytics & A/B Testing

Marvin EDORH 1 Sep 07, 2021
Python program that uses pynput to simulate key presses. Probably only works on Windows.

AutoKey Python program that uses pynput to simulate key presses. Probably only works on Windows. Can be used for pretty much whatever you want except

2 Oct 28, 2022
Getting the most out of your hobby servo

ServoProject by Adam Bäckström Getting the most out of your hobby servo Theory The control system of a regular hobby servo looks something like this:

209 Dec 20, 2022
Just a small test with lists in cython

Test for lists in cython Algorithm create a list of 10^4 lists each with 10^4 floats values (namely: 0.1) - 2 nested for iterate each list and compute

Federico Simonetta 32 Jul 23, 2022
A Python Selenium library inspired by the Testing Library

Selenium Testing Library Slenium Testing Library (STL) is a Python library for Selenium inspired by Testing-Library. Dependencies Python 3.6, 3.7, 3.8

Anže Pečar 12 Dec 26, 2022
Generates realistic traffic for load testing tile servers

Generates realistic traffic for load testing tile servers. Useful for: Measuring throughput, latency and concurrency of your tile serving stack. Ident

Brandon Liu 23 Dec 05, 2022
Faker is a Python package that generates fake data for you.

Faker is a Python package that generates fake data for you. Whether you need to bootstrap your database, create good-looking XML documents, fill-in yo

Daniele Faraglia 15.2k Jan 01, 2023
Aioresponses is a helper for mock/fake web requests in python aiohttp package.

aioresponses Aioresponses is a helper to mock/fake web requests in python aiohttp package. For requests module there are a lot of packages that help u

402 Jan 06, 2023
Python Moonlight (Machine Learning) Practice

PyML Python Moonlight (Machine Learning) Practice Contents Design Documentation Prerequisites Checklist Dev Setup Testing Run Prerequisites Python 3 P

Dockerian Seattle 2 Dec 25, 2022