SFTP test should run sequentially -> migrate these tests to pytest
This commit is contained in:
parent
ca01bf1196
commit
d2685f85a8
|
|
@ -779,7 +779,7 @@ if APP_ENVIRONMENT == "local":
|
||||||
# django-extensions
|
# django-extensions
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
|
||||||
INSTALLED_APPS += ["django_extensions", "django_watchfiles"] # noqa F405
|
INSTALLED_APPS += ["django_extensions"] # noqa F405
|
||||||
else:
|
else:
|
||||||
# not local
|
# not local
|
||||||
# SECURITY
|
# SECURITY
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
import pytest
|
||||||
|
from _pytest.runner import runtestprotocol
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.hookimpl(tryfirst=True)
|
||||||
|
def pytest_collection_modifyitems(config, items):
|
||||||
|
parallel_items = []
|
||||||
|
serial_items = []
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
if "serial" in item.keywords:
|
||||||
|
serial_items.append(item)
|
||||||
|
else:
|
||||||
|
parallel_items.append(item)
|
||||||
|
|
||||||
|
# Modify the collection to run serial tests first
|
||||||
|
config.serial_items = serial_items
|
||||||
|
items[:] = parallel_items
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.hookimpl(tryfirst=True)
|
||||||
|
def pytest_sessionfinish(session, exitstatus):
|
||||||
|
config = session.config
|
||||||
|
if hasattr(config, "serial_items") and config.serial_items:
|
||||||
|
serial_items = config.serial_items
|
||||||
|
|
||||||
|
# Run serial tests one by one
|
||||||
|
for item in serial_items:
|
||||||
|
runtestprotocol(item, nextitem=None)
|
||||||
|
|
@ -6,8 +6,8 @@ from io import StringIO
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
|
import pytest
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.test import TransactionTestCase
|
|
||||||
|
|
||||||
from vbv_lernwelt.core.admin import User
|
from vbv_lernwelt.core.admin import User
|
||||||
from vbv_lernwelt.core.create_default_users import create_default_users
|
from vbv_lernwelt.core.create_default_users import create_default_users
|
||||||
|
|
@ -17,116 +17,115 @@ from vbv_lernwelt.shop.invoice.abacus_sftp_client import AbacusSftpClient
|
||||||
from vbv_lernwelt.shop.tests.factories import CheckoutInformationFactory
|
from vbv_lernwelt.shop.tests.factories import CheckoutInformationFactory
|
||||||
|
|
||||||
|
|
||||||
class BaseAbacusSftpServerTestCase(TransactionTestCase):
|
@pytest.fixture(scope="module")
|
||||||
def setUp(self):
|
def sftp_server():
|
||||||
self.start_sftp_server()
|
tmppath = tempfile.mkdtemp()
|
||||||
|
print(tmppath)
|
||||||
|
shutil.rmtree(tmppath)
|
||||||
|
os.mkdir(tmppath)
|
||||||
|
os.mkdir(os.path.join(tmppath, "debitor"))
|
||||||
|
os.mkdir(os.path.join(tmppath, "order"))
|
||||||
|
sftp_server = Popen(
|
||||||
|
f"sftpserver -p {settings.ABACUS_EXPORT_SFTP_PORT} -l INFO",
|
||||||
|
shell=True,
|
||||||
|
cwd=tmppath,
|
||||||
|
)
|
||||||
|
sleep(3)
|
||||||
|
yield tmppath
|
||||||
|
if sftp_server:
|
||||||
|
sftp_server.kill()
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
if self.sftp_server:
|
|
||||||
self.sftp_server.kill()
|
|
||||||
|
|
||||||
def start_sftp_server(self):
|
def test_can_write_file_to_fake_sftp_server(sftp_server):
|
||||||
self.tmppath = tempfile.mkdtemp()
|
with AbacusSftpClient() as client:
|
||||||
print(self.tmppath)
|
files = client.listdir(".")
|
||||||
shutil.rmtree(self.tmppath)
|
assert set(files) == {"debitor", "order"}
|
||||||
os.mkdir(self.tmppath)
|
|
||||||
os.mkdir(self.tmppath + "/debitor")
|
str_file = StringIO()
|
||||||
os.mkdir(self.tmppath + "/order")
|
str_file.write("Hello world\n")
|
||||||
self.sftp_server = Popen(
|
str_file.seek(0)
|
||||||
f"sftpserver -p {settings.ABACUS_EXPORT_SFTP_PORT} -l INFO",
|
client.putfo(str_file, "hello.txt")
|
||||||
shell=True,
|
|
||||||
cwd=self.tmppath,
|
files = client.listdir(".")
|
||||||
|
assert set(files) == {"debitor", "order", "hello.txt"}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def setup_abacus_env(sftp_server):
|
||||||
|
add_countries(small_set=True)
|
||||||
|
create_default_users()
|
||||||
|
yield sftp_server
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.django_db
|
||||||
|
def test_upload_abacus_xml(setup_abacus_env):
|
||||||
|
tmppath = setup_abacus_env
|
||||||
|
|
||||||
|
# set abacus_number before
|
||||||
|
_pat = User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch")
|
||||||
|
_pat.abacus_debitor_number = 60000011
|
||||||
|
_pat.save()
|
||||||
|
_ignore_checkout_information = CheckoutInformationFactory(
|
||||||
|
user=_pat, abacus_order_id=6_000_000_123
|
||||||
|
)
|
||||||
|
|
||||||
|
feuz = User.objects.get(username="andreas.feuz@eiger-versicherungen.ch")
|
||||||
|
feuz_checkout_info = CheckoutInformationFactory(
|
||||||
|
user=feuz,
|
||||||
|
transaction_id="24021508331287484",
|
||||||
|
first_name="Andreas",
|
||||||
|
last_name="Feuz",
|
||||||
|
street="Eggersmatt",
|
||||||
|
street_number="32",
|
||||||
|
postal_code="1719",
|
||||||
|
city="Zumholz",
|
||||||
|
country_id="CH",
|
||||||
|
invoice_address="org",
|
||||||
|
organisation_detail_name="VBV",
|
||||||
|
organisation_street="Laupenstrasse",
|
||||||
|
organisation_street_number="10",
|
||||||
|
organisation_postal_code="3000",
|
||||||
|
organisation_city="Bern",
|
||||||
|
organisation_country_id="CH",
|
||||||
|
)
|
||||||
|
feuz_checkout_info.created_at = datetime(2024, 2, 15, 8, 33, 12, 0)
|
||||||
|
|
||||||
|
abacus_ssh_upload(feuz_checkout_info)
|
||||||
|
|
||||||
|
# check if files got created
|
||||||
|
debitor_filepath = os.path.join(tmppath, "debitor/myVBV_debi_60000012.xml")
|
||||||
|
assert os.path.exists(debitor_filepath)
|
||||||
|
|
||||||
|
with open(debitor_filepath) as debitor_file:
|
||||||
|
debi_content = debitor_file.read()
|
||||||
|
assert "<CustomerNumber>60000012</CustomerNumber>" in debi_content
|
||||||
|
assert "<Email>andreas.feuz@eiger-versicherungen.ch</Email>" in debi_content
|
||||||
|
|
||||||
|
order_filepath = os.path.join(
|
||||||
|
tmppath, "order/myVBV_orde_60000012_20240215083312_6000000124.xml"
|
||||||
|
)
|
||||||
|
assert os.path.exists(order_filepath)
|
||||||
|
with open(order_filepath) as order_file:
|
||||||
|
order_content = order_file.read()
|
||||||
|
assert (
|
||||||
|
"<ReferencePurchaseOrder>24021508331287484</ReferencePurchaseOrder>"
|
||||||
|
in order_content
|
||||||
)
|
)
|
||||||
sleep(3)
|
assert "<CustomerNumber>60000012</CustomerNumber>" in order_content
|
||||||
|
|
||||||
|
feuz_checkout_info.refresh_from_db()
|
||||||
|
assert feuz_checkout_info.abacus_ssh_upload_done
|
||||||
|
|
||||||
class AbacusSftpServerTestCase(BaseAbacusSftpServerTestCase):
|
# calling `abacus_ssh_upload` a second time will not upload files again...
|
||||||
def test_canWriteFile_toFakeSftpServer(self):
|
os.remove(debitor_filepath)
|
||||||
with AbacusSftpClient() as client:
|
os.remove(order_filepath)
|
||||||
files = client.listdir(".")
|
|
||||||
self.assertSetEqual({"debitor", "order"}, set(files))
|
|
||||||
|
|
||||||
str_file = StringIO()
|
abacus_ssh_upload(feuz_checkout_info)
|
||||||
str_file.write("Hello world\n")
|
|
||||||
str_file.seek(0)
|
|
||||||
client.putfo(str_file, "hello.txt")
|
|
||||||
|
|
||||||
files = client.listdir(".")
|
debitor_filepath = os.path.join(tmppath, "debitor/myVBV_debi_60000012.xml")
|
||||||
self.assertSetEqual({"debitor", "order", "hello.txt"}, set(files))
|
assert not os.path.exists(debitor_filepath)
|
||||||
|
|
||||||
|
order_filepath = os.path.join(
|
||||||
class AbacusInvoiceUploadTestCase(BaseAbacusSftpServerTestCase):
|
tmppath, "order/myVBV_orde_60000012_20240215083312_6000000124.xml"
|
||||||
def setUp(self):
|
)
|
||||||
super().setUp()
|
assert not os.path.exists(order_filepath)
|
||||||
add_countries(small_set=True)
|
|
||||||
create_default_users()
|
|
||||||
|
|
||||||
def test_upload_abacus_xml(self):
|
|
||||||
# set abacus_number before
|
|
||||||
_pat = User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch")
|
|
||||||
_pat.abacus_debitor_number = 60000011
|
|
||||||
_pat.save()
|
|
||||||
_ignore_checkout_information = CheckoutInformationFactory(
|
|
||||||
user=_pat, abacus_order_id=6_000_000_123
|
|
||||||
)
|
|
||||||
|
|
||||||
feuz = User.objects.get(username="andreas.feuz@eiger-versicherungen.ch")
|
|
||||||
feuz_checkout_info = CheckoutInformationFactory(
|
|
||||||
user=feuz,
|
|
||||||
transaction_id="24021508331287484",
|
|
||||||
first_name="Andreas",
|
|
||||||
last_name="Feuz",
|
|
||||||
street="Eggersmatt",
|
|
||||||
street_number="32",
|
|
||||||
postal_code="1719",
|
|
||||||
city="Zumholz",
|
|
||||||
country_id="CH",
|
|
||||||
invoice_address="org",
|
|
||||||
organisation_detail_name="VBV",
|
|
||||||
organisation_street="Laupenstrasse",
|
|
||||||
organisation_street_number="10",
|
|
||||||
organisation_postal_code="3000",
|
|
||||||
organisation_city="Bern",
|
|
||||||
organisation_country_id="CH",
|
|
||||||
)
|
|
||||||
feuz_checkout_info.created_at = datetime(2024, 2, 15, 8, 33, 12, 0)
|
|
||||||
|
|
||||||
abacus_ssh_upload(feuz_checkout_info)
|
|
||||||
|
|
||||||
# check if files got created
|
|
||||||
debitor_filepath = self.tmppath + "/debitor/myVBV_debi_60000012.xml"
|
|
||||||
self.assertTrue(os.path.exists(debitor_filepath))
|
|
||||||
|
|
||||||
with open(debitor_filepath) as debitor_file:
|
|
||||||
debi_content = debitor_file.read()
|
|
||||||
assert "<CustomerNumber>60000012</CustomerNumber>" in debi_content
|
|
||||||
assert "<Email>andreas.feuz@eiger-versicherungen.ch</Email>" in debi_content
|
|
||||||
|
|
||||||
order_filepath = (
|
|
||||||
self.tmppath + "/order/myVBV_orde_60000012_20240215083312_6000000124.xml"
|
|
||||||
)
|
|
||||||
self.assertTrue(os.path.exists(order_filepath))
|
|
||||||
with open(order_filepath) as order_file:
|
|
||||||
order_content = order_file.read()
|
|
||||||
assert (
|
|
||||||
"<ReferencePurchaseOrder>24021508331287484</ReferencePurchaseOrder>"
|
|
||||||
in order_content
|
|
||||||
)
|
|
||||||
assert "<CustomerNumber>60000012</CustomerNumber>" in order_content
|
|
||||||
|
|
||||||
feuz_checkout_info.refresh_from_db()
|
|
||||||
self.assertTrue(feuz_checkout_info.abacus_ssh_upload_done)
|
|
||||||
|
|
||||||
# calling `abacus_ssh_upload` a second time will not upload files again...
|
|
||||||
os.remove(debitor_filepath)
|
|
||||||
os.remove(order_filepath)
|
|
||||||
|
|
||||||
abacus_ssh_upload(feuz_checkout_info)
|
|
||||||
|
|
||||||
debitor_filepath = self.tmppath + "/debitor/myVBV_debi_60000012.xml"
|
|
||||||
self.assertFalse(os.path.exists(debitor_filepath))
|
|
||||||
|
|
||||||
order_filepath = (
|
|
||||||
self.tmppath + "/order/myVBV_orde_60000012_20240215083312_6000000124.xml"
|
|
||||||
)
|
|
||||||
self.assertFalse(os.path.exists(order_filepath))
|
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@
|
||||||
addopts = --ds=config.settings.test --no-migrations
|
addopts = --ds=config.settings.test --no-migrations
|
||||||
python_files = tests.py test_*.py
|
python_files = tests.py test_*.py
|
||||||
norecursedirs = node_modules
|
norecursedirs = node_modules
|
||||||
|
markers =
|
||||||
|
serial: marks tests as serial (not to be run in parallel)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ django-stubs # https://github.com/typeddjango/django-stubs
|
||||||
pytest # https://github.com/pytest-dev/pytest
|
pytest # https://github.com/pytest-dev/pytest
|
||||||
pytest-sugar # https://github.com/Frozenball/pytest-sugar
|
pytest-sugar # https://github.com/Frozenball/pytest-sugar
|
||||||
pytest-xdist #
|
pytest-xdist #
|
||||||
|
pytest-order
|
||||||
djangorestframework-stubs # https://github.com/typeddjango/djangorestframework-stubs
|
djangorestframework-stubs # https://github.com/typeddjango/djangorestframework-stubs
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,9 +34,6 @@ django-coverage-plugin # https://github.com/nedbat/django_coverage_plugin
|
||||||
pytest-django # https://github.com/pytest-dev/pytest-django
|
pytest-django # https://github.com/pytest-dev/pytest-django
|
||||||
freezegun # https://github.com/spulec/freezegun
|
freezegun # https://github.com/spulec/freezegun
|
||||||
|
|
||||||
# django-watchfiles custom PR
|
|
||||||
https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
|
||||||
|
|
||||||
# code checking
|
# code checking
|
||||||
truffleHog
|
truffleHog
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,6 @@ django==3.2.20
|
||||||
# django-stubs-ext
|
# django-stubs-ext
|
||||||
# django-taggit
|
# django-taggit
|
||||||
# django-treebeard
|
# django-treebeard
|
||||||
# django-watchfiles
|
|
||||||
# djangorestframework
|
# djangorestframework
|
||||||
# drf-spectacular
|
# drf-spectacular
|
||||||
# graphene-django
|
# graphene-django
|
||||||
|
|
@ -186,8 +185,6 @@ django-taggit==4.0.0
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-treebeard==4.7
|
django-treebeard==4.7
|
||||||
# via wagtail
|
# via wagtail
|
||||||
django-watchfiles @ https://github.com/q0w/django-watchfiles/archive/issue-1.zip
|
|
||||||
# via -r requirements-dev.in
|
|
||||||
djangorestframework==3.14.0
|
djangorestframework==3.14.0
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
|
|
@ -416,10 +413,13 @@ pytest==7.4.0
|
||||||
# via
|
# via
|
||||||
# -r requirements-dev.in
|
# -r requirements-dev.in
|
||||||
# pytest-django
|
# pytest-django
|
||||||
|
# pytest-order
|
||||||
# pytest-sugar
|
# pytest-sugar
|
||||||
# pytest-xdist
|
# pytest-xdist
|
||||||
pytest-django==4.5.2
|
pytest-django==4.5.2
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
|
pytest-order==1.2.1
|
||||||
|
# via -r requirements-dev.in
|
||||||
pytest-sugar==0.9.7
|
pytest-sugar==0.9.7
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
pytest-xdist==3.5.0
|
pytest-xdist==3.5.0
|
||||||
|
|
@ -609,9 +609,7 @@ wagtail-headless-preview==0.6.0
|
||||||
wagtail-localize==1.5.1
|
wagtail-localize==1.5.1
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
watchfiles==0.19.0
|
watchfiles==0.19.0
|
||||||
# via
|
# via uvicorn
|
||||||
# django-watchfiles
|
|
||||||
# uvicorn
|
|
||||||
wcwidth==0.2.6
|
wcwidth==0.2.6
|
||||||
# via prompt-toolkit
|
# via prompt-toolkit
|
||||||
webencodings==0.5.1
|
webencodings==0.5.1
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,7 @@ azure-core==1.29.1
|
||||||
azure-identity==1.14.0
|
azure-identity==1.14.0
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
azure-storage-blob==12.17.0
|
azure-storage-blob==12.17.0
|
||||||
# via
|
# via -r requirements.in
|
||||||
# -r requirements.in
|
|
||||||
bcrypt==4.0.1
|
bcrypt==4.0.1
|
||||||
# via paramiko
|
# via paramiko
|
||||||
beautifulsoup4==4.11.2
|
beautifulsoup4==4.11.2
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
# limit test to 6 parallel processes, otherwise ratelimit of s3 could be hit
|
# limit test to 6 parallel processes, otherwise ratelimit of s3 could be hit
|
||||||
pytest --numprocesses auto --maxprocesses=6 --junitxml=../test-reports/coverage.xml
|
pytest --numprocesses auto --maxprocesses=6 --dist=loadscope --junitxml=../test-reports/coverage.xml $1
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
coverage run -m pytest --numprocesses auto --maxprocesses=6 --junitxml=../test-reports/coverage.xml $1
|
pytest --numprocesses auto --maxprocesses=6 --dist=loadscope --junitxml=../test-reports/coverage.xml $1
|
||||||
|
|
||||||
coverage_python=`coverage report -m | tail -n1 | awk '{print $4}'`
|
coverage_python=`coverage report -m | tail -n1 | awk '{print $4}'`
|
||||||
commit=`git rev-parse HEAD`
|
commit=`git rev-parse HEAD`
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class AbacusInvoiceTestCase(TestCase):
|
||||||
invoice_xml_filename, "myVBV_orde_60000012_20240215083312_6000000124.xml"
|
invoice_xml_filename, "myVBV_orde_60000012_20240215083312_6000000124.xml"
|
||||||
)
|
)
|
||||||
|
|
||||||
# print(invoice_xml_content)
|
print(invoice_xml_content)
|
||||||
assert "<CustomerNumber>60000012</CustomerNumber>" in invoice_xml_content
|
assert "<CustomerNumber>60000012</CustomerNumber>" in invoice_xml_content
|
||||||
assert (
|
assert (
|
||||||
"<PurchaseOrderDate>2024-02-15</PurchaseOrderDate>" in invoice_xml_content
|
"<PurchaseOrderDate>2024-02-15</PurchaseOrderDate>" in invoice_xml_content
|
||||||
|
|
@ -61,7 +61,7 @@ class AbacusInvoiceTestCase(TestCase):
|
||||||
)
|
)
|
||||||
assert "<DeliveryDate>2024-02-15</DeliveryDate>" in invoice_xml_content
|
assert "<DeliveryDate>2024-02-15</DeliveryDate>" in invoice_xml_content
|
||||||
assert (
|
assert (
|
||||||
"<Text>Versicherungsvermittler/-in VBV - 2024-02-15 - Feuz Andreas</Text>"
|
"<Text>Versicherungsvermittler/-in VBV, 2024-02-15, Feuz Andreas</Text>"
|
||||||
in invoice_xml_content
|
in invoice_xml_content
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue