test: use instant accounts instead of mailadm

This commit is contained in:
link2xt
2023-10-17 21:26:04 +00:00
parent 1d80659bc3
commit 6aae0276da
16 changed files with 101 additions and 94 deletions

View File

@@ -53,14 +53,14 @@ end-to-end tests that require accounts on real e-mail servers.
Running "live" tests with temporary accounts
--------------------------------------------
If you want to run live functional tests you can set ``DCC_NEW_TMP_EMAIL`` to a URL that creates e-mail accounts. Most developers use https://testrun.org URLs created and managed by `mailadm <https://mailadm.readthedocs.io/>`_.
If you want to run live functional tests
you can set ``CHATMAIL_DOMAIN`` to a domain of the email server
that creates e-mail accounts like this::
Please feel free to contact us through a github issue or by e-mail and we'll send you a URL that you can then use for functional tests like this::
export CHATMAIL_DOMAIN=nine.testrun.org
export DCC_NEW_TMP_EMAIL=<URL you got from us>
With this account-creation setting, pytest runs create ephemeral e-mail accounts on the http://testrun.org server.
These accounts are removed automatically as they expire.
With this account-creation setting, pytest runs create ephemeral e-mail accounts on the server.
These accounts have the pattern `ci-{6 characters}@{CHATMAIL_DOMAIN}`.
After setting the variable, either rerun `scripts/run-python-test.sh`
or run offline and online tests with `tox` directly::
@@ -159,6 +159,6 @@ find it with::
This docker image can be used to run tests and build Python wheels for all interpreters::
$ docker run -e DCC_NEW_TMP_EMAIL \
$ docker run -e CHATMAIL_DOMAIN \
--rm -it -v $(pwd):/mnt -w /mnt \
deltachat/coredeps scripts/run_all.sh

View File

@@ -8,11 +8,11 @@ import sys
import threading
import time
import weakref
import random
from queue import Queue
from typing import Callable, Dict, List, Optional, Set
import pytest
import requests
from _pytest._code import Source
import deltachat
@@ -29,6 +29,12 @@ def pytest_addoption(parser):
default=None,
help="a file with >=2 lines where each line contains NAME=VALUE config settings for one account",
)
group.addoption(
"--chatmail",
action="store",
default=None,
help="chatmail server domain name",
)
group.addoption(
"--ignored",
action="store_true",
@@ -53,10 +59,12 @@ def pytest_addoption(parser):
def pytest_configure(config):
cfg = config.getoption("--liveconfig")
cfg = config.getoption("--chatmail")
if not cfg:
cfg = os.getenv("DCC_NEW_TMP_EMAIL")
cfg = os.getenv("CHATMAIL_DOMAIN")
if cfg:
config.option.liveconfig = cfg
config.option.chatmail = cfg
# Make sure we don't get garbled output because threads keep running
# collect all ever created accounts in a weakref-set (so we don't
@@ -157,13 +165,29 @@ class TestProcess:
"""provide live account configs, cached on a per-test-process scope
so that test functions can re-use already known live configs.
Depending on the --liveconfig option this comes from
a HTTP provider or a file with a line specifying each accounts config.
a file with a line specifying each accounts config
or a --chatmail domain.
"""
liveconfig_opt = self.pytestconfig.getoption("--liveconfig")
if not liveconfig_opt:
pytest.skip("specify DCC_NEW_TMP_EMAIL or --liveconfig to provide live accounts")
if not liveconfig_opt.startswith("http"):
chatmail_opt = self.pytestconfig.getoption("--chatmail")
if chatmail_opt:
# Use a chatmail instance.
domain = chatmail_opt
MAX_LIVE_CREATED_ACCOUNTS = 10
for index in range(MAX_LIVE_CREATED_ACCOUNTS):
try:
yield self._configlist[index]
except IndexError:
username = "ci-" + "".join(random.choice("2345789acdefghjkmnpqrstuvwxyz") for i in range(6))
password = f"{username}${username}"
addr = f"{username}@{domain}"
config = {"addr": addr, "mail_pw": password}
print("newtmpuser {}: addr={}".format(index, config["addr"]))
self._configlist.append(config)
yield config
pytest.fail(f"more than {MAX_LIVE_CREATED_ACCOUNTS} live accounts requested.")
elif liveconfig_opt:
# Read a list of accounts from file.
for line in open(liveconfig_opt):
if line.strip() and not line.strip().startswith("#"):
d = {}
@@ -174,20 +198,9 @@ class TestProcess:
yield from iter(self._configlist)
else:
MAX_LIVE_CREATED_ACCOUNTS = 10
for index in range(MAX_LIVE_CREATED_ACCOUNTS):
try:
yield self._configlist[index]
except IndexError:
res = requests.post(liveconfig_opt, timeout=60)
if res.status_code != 200:
pytest.fail(f"newtmpuser count={index} code={res.status_code}: '{res.text}'")
d = res.json()
config = {"addr": d["email"], "mail_pw": d["password"]}
print("newtmpuser {}: addr={}".format(index, config["addr"]))
self._configlist.append(config)
yield config
pytest.fail(f"more than {MAX_LIVE_CREATED_ACCOUNTS} live accounts requested.")
pytest.skip(
"specify --liveconfig, CHATMAIL_DOMAIN or --chatmail to provide live accounts",
)
def cache_maybe_retrieve_configured_db_files(self, cache_addr, db_target_path):
db_target_path = pathlib.Path(db_target_path)

View File

@@ -2208,7 +2208,17 @@ def test_delete_multiple_messages(acfactory, lp):
def test_trash_multiple_messages(acfactory, lp):
ac1, ac2 = acfactory.get_online_accounts(2)
# Create the Trash folder on IMAP server
# and recreate the account so Trash folder is configured.
lp.sec("Creating trash folder")
ac2.direct_imap.create_folder("Trash")
lp.sec("Creating new accounts")
ac2 = acfactory.new_online_configuring_account(cloned_from=ac2)
acfactory.bring_accounts_online()
ac2.set_config("delete_to_trash", "1")
assert ac2.get_config("configured_trash_folder")
chat12 = acfactory.get_accepted_chat(ac1, ac2)
lp.sec("ac1: sending 3 messages")
@@ -2239,13 +2249,15 @@ def test_trash_multiple_messages(acfactory, lp):
def test_configure_error_msgs_wrong_pw(acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
ac1.update_config(configdict)
ac1.set_config("mail_pw", "abc") # Wrong mail pw
ac1.configure()
(ac1,) = acfactory.get_online_accounts(1)
ac2 = acfactory.get_unconfigured_account()
ac2.set_config("addr", ac1.get_config("addr"))
ac2.set_config("mail_pw", "abc") # Wrong mail pw
ac2.configure()
while True:
ev = ac1._evtracker.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
ev = ac2._evtracker.get_matching("DC_EVENT_CONFIGURE_PROGRESS")
print(f"Configuration progress: {ev.data1}")
if ev.data1 == 0:
break
# Password is wrong so it definitely has to say something about "password"
@@ -2548,7 +2560,7 @@ class TestOnlineConfigureFails:
def test_invalid_user(self, acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
configdict["addr"] = "x" + configdict["addr"]
configdict["addr"] = "$" + configdict["addr"]
ac1.update_config(configdict)
configtracker = ac1.configure()
configtracker.wait_progress(500)
@@ -2557,7 +2569,7 @@ class TestOnlineConfigureFails:
def test_invalid_domain(self, acfactory):
configdict = acfactory.get_next_liveconfig()
ac1 = acfactory.get_unconfigured_account()
configdict["addr"] += "x"
configdict["addr"] += "$"
ac1.update_config(configdict)
configtracker = ac1.configure()
configtracker.wait_progress(500)

View File

@@ -16,7 +16,7 @@ setenv =
passenv =
DCC_RS_DEV
DCC_RS_TARGET
DCC_NEW_TMP_EMAIL
CHATMAIL_DOMAIN
CARGO_TARGET_DIR
RUSTC_WRAPPER
deps =