Package: pytest-mysql
pytest-mysqlWhat is this?This is a pytest plugin, that enables you to test your code that relies on a running MySQL Database.
It allows you to specify fixtures for MySQL process and client.WarningOnly MySQL 5.7.6 and up are supported. For older versions, please use pytest-mysql 2.0.3
Although Pull Request to add back support for older MySQL versions are welcome.How to usePlugin contains two fixturesmysql- it’s a client fixture that has functional scope. After each test drops test database from MySQL ensuring repeatability.mysql_proc- session scoped fixture, that starts MySQL instance at it’s first use and stops at the end of the tests.mysql_noproc- session scoped fixtures, that allows to connect to already existing MySQL instance, and cleans the database at the end of the testsSimply include one of these fixtures into your tests fixture list.You can also create additional mysql client and process fixtures if you’d need to:frompytest_mysqlimportfactoriesfromgetpassimportgetuser()mysql_my_proc=factories.mysql_proc(port=None,user=getuser())mysql_my=factories.mysql('mysql_my_proc')NoteEach MySQL process fixture can be configured in a different way than the others through the fixture factory arguments.ConfigurationYou can define your settings in three ways, it’s fixture factory argument, command line option and pytest.ini configuration option.
You can pick which you prefer, but remember that these settings are handled in the following order:Fixture factory argumentCommand line optionConfiguration option in your pytest.ini fileConfiguration optionsMySQL/MariaDB optionFixture factory argumentCommand line optionpytest.ini optionNoop process fixtureDefaultPath to executablemysqld_exec–mysql-mysqldmysql_mysqldmysqldPath to safe executablemysqld_safe–mysql-mysqld-safemysql_mysqld_safemysqld_safePath to mysql_install_db for legacy installationsinstall_db–mysql-install-dbmysql_install_dbmysql_install_dbPath to Admin executableadmin_executable–mysql-adminmysql_adminmysqladminDatabase hostnamehost–mysql-hostmysql_hostyeslocalhostDatabase portport–mysql-portmysql_portyes (3306)randomMySQL user to work withuser–mysql-usermysql_userrootUser’s passwordpasswd–mysql-passwdmysql_passwdTest database namedbname–mysql-dbnamemysql_dbnametestStarting parametersparams–mysql-paramsmysql_paramsLog directory location [DEPRECATED]logsdir–mysql-logsdirmysql_logsdir$TMPDIRExample usage:pass it as an argument in your own fixturemysql_proc=factories.mysql_proc(port=8888)use--mysql-portcommand line option when you run your testspy.test tests --mysql-port=8888specify your port asmysql_portin yourpytest.inifile.To do so, put a line like the following under the[pytest]section of yourpytest.ini:[pytest]mysql_port=8888ExamplesPopulating database for testsWith SQLAlchemyThis example shows how to populate database and create an SQLAlchemy’s ORM connection:Sample below is simplified session fixture frompyramid_fullauthtests:fromsqlalchemyimportcreate_enginefromsqlalchemy.ormimportscoped_session,sessionmakerfromsqlalchemy.poolimportNullPoolfromzope.sqlalchemyimportregister@pytest.fixturedefdb_session(mysql):"""Session for SQLAlchemy."""frompyramid_fullauth.modelsimportBase# pylint:disable=import-outside-toplevel# assumes setting, these can be obtained from pytest-mysql config or mysql_procconnection=f'mysql+mysqldb://root:@127.0.0.1:3307/tests?charset=utf8'engine=create_engine(connection,echo=False,poolclass=NullPool)pyramid_basemodel.Session=scoped_session(sessionmaker(extension=ZopeTransactionExtension()))pyramid_basemodel.bind_engine(engine,pyramid_basemodel.Session,should_create=True,should_drop=True)yieldpyramid_basemodel.Sessiontransaction.commit()Base.metadata.drop_all(engine)@pytest.fixturedefuser(db_session):"""Test user fixture."""frompyramid_fullauth.modelsimportUserfromtests.toolsimportDEFAULT_USERnew_user=User(**DEFAULT_USER)db_session.add(new_user)transaction.commit()returnnew_userdeftest_remove_last_admin(db_session,user):"""
    Sample test checks internal login, but shows usage in tests with SQLAlchemy
    """user=db_session.merge(user)user.is_admin=Truetransaction.commit()user=db_session.merge(user)withpytest.raises(AttributeError):user.is_admin=FalseNoteSee the original code atpyramid_fullauth’s conftest file.
Depending on your needs, that in between code can fire alembic migrations in case of sqlalchemy stack or any other codeConnecting to MySQL/MariaDB (in a docker)To connect to a docker run MySQL and run test on it, use noproc fixtures.dockerrun--namesome-db-eMYSQL_ALLOW_EMPTY_PASSWORD=yes-dmysql--expose3306dockerrun--namesome-db-eMARIADB_ALLOW_EMPTY_PASSWORD=yes-dmariadb--expose3306This will start MySQL in a docker container, however using a MySQL installed locally is not much different.In tests, make sure that all your tests are usingmysql_noprocfixture like that:mysql_in_docker=factories.mysql_noproc()mysql=factories.mysql("mysql_in_docker")deftest_mysql_docker(mysql):"""Run test."""cur=mysql.cursor()cur.query("CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20), species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);")mysql.commit()cur.close()And run tests:pytest--mysql-host=127.0.0.1Running on Docker/as rootUnfortunately, running MySQL as root (thus by default on docker) is not possible.
MySQL (and MariaDB as well) will not allow it.USER nobodyThis line should switch your docker process to run on user nobody. Seethis comment for examplePackage resourcesBug tracker:https://github.com/ClearcodeHQ/pytest-mysql/issuesReleaseInstall pipenv and –dev dependencies first, Then run:pipenv run tbump [NEW_VERSION]