No project description provided
Project description
pyFuncTest
The framework for functional testing of microservices
Functional сapabilities:
- Build a container from git repository
- Create, start and stop containers
- Send and receive messages from Kafka, RabbitMQ
- Write and read data from mySQL, MariaDB, PostgreSQL
- Write and read files from FTP, MinIO
Additional:
- You can create folders before running tests for FTP, MinIO
- You can migrate structure and data before running tests for databases
- You can replace configuration and other files inside container before work
- You can run docker services in a specific sequence before running tests
Table of Contents
Install
pip3 install pyfunctest
Upgrade
pip3 install --upgrade pyfunctest
How it works
Settings of modules
The main module is FMods. Its constructor has three parameters: path to settings, path to template folder and verbose. The example of structure settings: https://github.com/Lunkov/pyfunctest/tree/master/data/mods
The example commands for tests
import unittest
class TestServices(unittest.TestCase):
def setUp(self):
# New object of settings of modules
self.fm = FMods("mods/", "tmp/", True)
# Read settings
self.fm.scan()
# Run all containers
self.fm.startAll()
def testReceiveMessage(self):
# New object of RabbitMQ Client
rabbitmq = self.fm.newRabbitMQ('rabbitmq')
# Create routes
queue = 'log3'
exchange = 'log3'
routing_key = ''
exchange_type = 'fanout'
self.assertTrue(rabbitmq.createRoute(exchange, exchange_type, routing_key, queue))
# Send message
self.assertTrue(rabbitmq.send(exchange, routing_key, 'message 1'))
# New object of PostgreSQL Client
pg = self.fm.newPostgre('pg')
# Check structure of database
self.assertEqual(pg.getTableList(), [('public', 'messages')])
# Get and check data from table
self.assertEqual(pg.getData('select * from public.messages'), [(1, 'message 1')])
def tearDown(self):
# Stop all containers
self.fm.stopAll()
if __name__ == '__main__':
unittest.main()
Docker
Build container
Example file .yaml
name: srv-report
actions:
- build
git:
src: "https://github.com/Lunkov/srv-report.git"
branch: master
docker:
name: srv-report-test
src: srv-report-test
dockerfile: Dockerfile
buildpath: .
Commands for tests
# New object of settings of modules
fm = FMods("mods/", "tmp/", True)
# Read settings
fm.scan()
# Get module
srvDocker = fm.newDocker('srv-report')
# Container must have status: not found
self.assertTrue(srvDocker.statusWaiting('not found'))
# Build container
self.assertTrue(srvDocker.build())
# Run container
self.assertTrue(srvDocker.run())
Start container
Example file .yaml
name: nginx
order: 10
actions:
- run
docker:
name: nginx-test
src: nginx
ports:
- "3010:81"
env:
- NGINX_PORT: 81
volumes:
- "data/mods/nginx/html/:/usr/share/nginx/html:ro"
- "data/mods/nginx/test.conf:/etc/nginx/conf.d/default.conf"
Commands for tests
# New object of settings of modules
fm = FMods("mods/", "tmp/", True)
# Read settings
fm.scan()
# Get module
srvNginx = fm.newDocker('nginx')
# Run container
self.assertTrue(srvNginx.run())
# Container must have status: running
self.assertEqual(srvNginx.status(), 'running')
Start compose
Example file .yaml
name: kafka
order: 1
actions:
- run
- init
docker:
name: kafka_kafka-test_1
compose: docker-compose.yml
network: test-net
init:
create_channels:
- channel-test
- channel1-test
- channel2-test
kafka:
url_inside: "localhost:9092"
url_outside: "localhost:9094"
id_group: main
Commands for tests
# New object of settings of modules
fm = FMods("mods/", "tmp/", True)
# Read settings
fm.scan()
# Get module
srvDocker = fm.newDocker('kafka') # Docker Compose
# Run container
self.assertTrue(srvDocker.startCompose())
# Container must have status: running
self.assertEqual(srvDocker.status(), 'running')
# Stop container
self.assertTrue(srvDocker.stopCompose())
FTP
Settings
Example file .yaml
name: ftp
order: 5
actions:
- run
docker:
name: ftp-test
src: teezily/ftpd
ports:
- "3021:21"
- "35000-35004:35000-35004"
patch:
- start-ftp: /
env:
- FTP_USER: user
- FTP_PASSWORD: pwd
- PASV_MIN_PORT: 35000
- PASV_MAX_PORT: 35004
ftp:
user: user
password: pwd
port: 3021
init:
# You can create folders before running tests
create_folders:
- folder-test/folder-test1
- folder-test/folder-test2
- folder-test1
Testing
# New object of FTP Client
ftp = fm.newFTP('ftp')
# Check structure of folder
self.assertEqual(ftp.getDirList(), ['incoming'])
# Upload file
self.assertTrue(ftp.uploadFile('folder-test', 'test.txt', 'data/files/test.txt'))
# Compare local and remote files
self.assertTrue(ftp.compareFiles('folder-test', 'test.txt', 'data/files/test.txt'))
Minio
Settings
Example file .yaml
name: minio
order: 6
actions:
- run
- init
docker:
name: minio-test
src: minio/minio
ports:
- "3010:9000"
run_command: "server /data"
s3:
access_key: minioadmin
secret_key: minioadmin
port: 3010
init:
# You can create folders before running tests
create_folders:
- "bucket-test:folder000"
- "bucket-test2:folder1/folder1"
Testing
# New object of Minio Client
minio = fm.newMinIO('minio')
# Check structure of basket
self.assertEqual(minio.getBasketsList(), ['bucket-test'])
# Upload file
self.assertTrue(minio.uploadFile('bucket-test', 'test.txt', 'data/files/test.txt'))
# Compare local and remote files
self.assertTrue(minio.compareFiles('bucket-test', 'test.txt', 'data/files/test.txt'))
MySQL
Settings
Example file .yaml
name: mysql
order: 2
actions:
- run
- migrate
docker:
name: mysql-test
src: mariadb
ports:
- "17436:3306"
# You can replace configuration file inside container before work
patch:
- 50-server.cnf: /etc/mysql/mariadb.conf.d/
env:
- MYSQL_ROOT_PASSWORD: pwd
- MYSQL_USER: user
- MYSQL_PASSWORD: pwd
- MYSQL_DATABASE: test-db
- ALLOW_EMPTY_PASSWORD: yes
db:
name: test-db
user: root
password: pwd
port: 17436
# You can migrate your data before tests
migrate:
command: "--path=/migrations/ --database=\"mysql://root:pwd@tcp(mysql-test:3306)/test-db\" up"
path: migrations
timeout_before_migrate: 10
Testing
Commands for tests
# New object of mySQL Client
msql = fm.newMySQL('mysql')
# Check structure of database
self.assertEqual(msql.getTableList(), ['article', 'article2', 'article3'])
# Create table
self.assertTrue(msql.loadSQL('data/mysql/create_tables.sql'))
# Insert Data
self.assertTrue(msql.loadSQL('data/mysql/insert.sql'))
# Get and check data from table
self.assertEqual(msql.getData('select * from article'), ((1, 'article 1', 'description'),))
PostgreSQL
Settings
Example file .yaml
name: pg
actions:
- run
- migrate
docker:
name: pg-test
src: postgres:alpine
ports:
- "17432:5432"
env:
- POSTGRES_PASSWORD: pwd
- POSTGRES_USER: user
- POSTGRES_DB: test-db
db:
name: test-db
user: user
password: pwd
port: 17432
migrate:
command: --path=/migrations/ --database="postgres://user:pwd@pg-test:5432/test-db?sslmode=disable" up
path: migrate
timeout_before_migrate: 5
Testing
# New object of PostgreSQL Client
pg = fm.newPostgre('pg')
# Check structure of database
self.assertEqual(pg.getTableList(), [('public', 'article'), ('public', 'article2'), ('public', 'article3')])
# Create table
self.assertTrue(pg.loadSQL('data/postgre/create_table.sql'))
# Insert Data
self.assertTrue(pg.loadSQL('data/postgre/insert.sql'))
# Get and check data from table
self.assertEqual(pg.getData('select * from public.article'), [(1, 'article 1', 'description', None)])
RabbitMQ
Settings
Example file .yaml
name: rabbitmq
actions:
- run
- init
docker:
name: rabbitmq-test
src: rabbitmq:management-alpine
ports:
- "5672:5672"
- "15672:15672"
env:
- RABBITMQ_DEFAULT_USER: user
- RABBITMQ_DEFAULT_PASS: pwd
- RABBITMQ_DEFAULT_VHOST: /
rabbitmq:
url: "amqp://user:pwd@localhost:5672/"
user: user
password: pwd
init:
# You can create channels before running tests
create_channels:
- "log3:fanout::log3"
- "log1:fanout::log1"
Testing
# New object of RabbitMQ Client
rabbitmq = fm.newRabbitMQ('rabbitmq')
# Create routes
self.assertTrue(rabbitmq.createRoute(exchange, exchange_type, routing_key, queue))
# Send message
self.assertTrue(rabbitmq.send(exchange, routing_key, 'message 1'))
# Recieve message
msg, ok = rabbitmq.receive(queue)
self.assertTrue(ok)
self.assertEqual(msg, 'message 1')
# Send file
self.assertTrue(rabbitmq.sendFile(exchange, routing_key, 'data/files/test.txt'))
# Recieve and compare file
self.assertTrue(rabbitmq.receiveAndCompareFile(queue, 'data/files/test.txt'))
Kafka
Settings
Example file .yaml
name: kafka
order: 1
actions:
- run
- init
docker:
name: kafka_kafka-test_1
compose: docker-compose.yml
network: test-net
init:
# You can create channels before running tests
create_channels:
- channel-test
- channel1-test
- channel2-test
kafka:
url_inside: "localhost:9092"
url_outside: "localhost:9094"
id_group: main
Testing
# New object of Kafka Client
kafka = fm.newKafka('kafka')
# Send message
self.assertTrue(kafka.send(channel, 'message 1'))
# Recieve message
msg, ok = kafka.receive(channel)
self.assertTrue(ok)
self.assertEqual(msg, 'message 1')
# Send file
self.assertTrue(kafka.sendFile(channel, 'data/files/test.txt'))
# Recieve and compare file
self.assertTrue(kafka.receiveAndCompareFile(channel, 'data/files/test.txt'))