#pytest #python-3.7 #assert
#пытест #python-3.7 #утверждать
Вопрос:
Используя Pytest
, я пытаюсь протестировать простую функцию базы read
update
данных и функцию. Сначала update
необходимо запустить функцию, чтобы убедиться, что в тестовой базе данных есть значения, которые мы будем проверять в нашей read
функции.
/src
Там мой основной скрипт, вот функции read
, update
, delete
:
async def read(self, collection, query=None, mods=None): Table = self._cache.classes[collection] async with self._session() as session: matches = set(Table.__mapper__.columns.keys()) amp; set(mods['fields']) for m in matches: q = select(getattr(Table, m)) q = q.filter_by(**query) result = await session.execute(q) return [row for row in result] async def update(self, collection, query, data): Table = self._cache.classes[collection] async with self._session() as s: q = sa_update(Table).filter_by(**query) q = q.values(**data) await s.execute(q) await s.commit() async def delete_collection(self, table_name, syncro_engine=sync_engine): table = self.retrieve_table_obj(table_name) async with self._engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all(syncro_engine, [table], checkfirst=True))
При запуске read
вывод [('Wonderland',)]
таков, что это то, в чем я провожу тестирование assert
Pytest
.
У /test
меня есть conftest.py
файл, в котором есть эти три функции:
@pytest.fixture(scope='function') def test_update(): def get_update(collection, query, data): return asyncio.run(DB.update(collection, query, data)) return get_update @pytest.fixture(scope='function') def test_read(): def get_read(collection, query, mods): return asyncio.run(DB.read(collection, query, mods)) return get_read @pytest.fixture(scope='function') def drop_table(): def get_delete_tables(table_name, sync_engine): return asyncio.run(DB.delete_collection(table_name, sync_engine)) return get_delete_tables
Затем тесты запускаются в test_db.py
:
# Tests 'update' by updating user 'Alice' with 'org' 'Wonderland' # Doesn't return anything, using it to ensure the correct values are in test_db to test the read function @pytest.mark.parametrize('function_input, expected', [("'user', {'name': 'Alice'}, {'org': 'Wonderland'})", "[('Wonderland',)]")]) def test_update(test_update, function_input, expected): test_update # Tests 'read' by reading the just-updated values @pytest.mark.parametrize('function_input, expected', [("'user', query={'name': 'Alice'}, mods={'fields': ['name', 'org']})", "[('Wonderland',)]")]) def test_read(test_read, function_input, expected): assert test_read == expected # Tests that tables are dropped cleanly by dropping a given table then checking for that table name @pytest.mark.parametrize('fn_input1, fn_input2, expected', [('image', sync_engine, 'image')]) def test_drop_table(drop_table, collection_names, fn_input1, fn_input2, expected): # First drop the table drop_table(fn_input1, fn_input2) # Now check that it no longer exists with pytest.raises(KeyError) as error_info: assert fn_input1 in collection_names raise KeyError assert error_info.type is KeyError
Запуск test_drop_table
ничего не отбрасывает test_db
, даже если ему передается правильная база test_db
данных и ее аналог в основном скрипте /src
работает должным образом.
Когда я запускаю этот test_read
тест, он терпит неудачу:
gt; assert test_read == expected E assert lt;function test_read.lt;localsgt;.get_read at 0x7f1fa6beed08gt; == "[('Wonderland',)]"
Как я могу получить доступ к фактическому возвращаемому значению assert
«против», т. Е. [('Wonderland',)]
, а не lt;function objectgt;
«против»?
Комментарии:
1. Когда вы возвращаете объект функции в своем устройстве, вы должны вызвать эту функцию в своем тесте. В качестве отступления — вероятно , не стоит называть ваши приборы
test_xxx
, тем более, что они имеют то же название, что и фактические тесты.2. Спасибо! Можете ли вы уточнить, что вы имеете в виду, вызывая эту функцию в моем тесте? Например, внутри
conftest.py
есть приспособлениеdrop_table
, которое вызываетget_delete_tables
. Он настроен таким образом, чтобы я мог передавать параметры изtest_db.py
функции, вызываемой устройством. На самом деле мне не нужно заявление о возвратеget_delete_tables
. Мне просто нужно получить доступ к вызовам основной функции скрипта (asyncio.run(DB.delete_collection(table_name, sync_engine))
)get_delete_tables
. Поэтому , чтобы вызвать это приспособление в тесте, я вызываюdrop_tables
и передаю параметры в «get_delete_tables».3. Все ваши приборы ничего не делают, они просто возвращают указатель на функцию. В
test_drop_table
вы на самом деле вызываете функцию, но в других тестах вы этого не делаете. Я на самом деле не понимаю, что должны делать тесты — описаниеtest_update
звучит так, как будто это задумано как настройка, хотя в этом случае оно должно быть приспособлением и на самом деле должно что-то делать (в настоящее время оно ничего не делает). Второй тест также ничего не вызывает, он просто сравнивает указатель функции с srguments — я ожидал бы, что вы захотите вызвать функцию вместо этого.4. Да, похоже, вам здесь не нужно приспособление. Вы можете использовать приспособления без возвращаемого значения, особенно для функций, подобных настройке/демонтажу (где вы выполняете настройку до
yield
и демонтаж послеyield
), но в этом случае вы должны знать аргументы для вызова в приспособлении, которых у вас, вероятно, нет в вашем случае.5. Да, если под «вызывает это приспособление» вы имеете в виду «поместите его имя в аргументы теста». Существует также @pytest.mark.usefixtures, которые могут использоваться в модуле или классе.