Exemplo n.º 1
0
def test_multiple_relaties(migrated_postgres, client):
    dataset = [
        generate_citizen(citizen_id=1,
                         birth_date="2019-12-31",
                         relatives=[2, 3]),
        generate_citizen(citizen_id=2, birth_date="2020-02-11", relatives=[1]),
        generate_citizen(citizen_id=3, birth_date="2020-02-17", relatives=[1]),
    ]
    r = client.post("/imports", json={"data": dataset})
    import_id = r.json()["data"]["import_id"]
    url = f"/imports/{import_id}/citizens/birthdays"

    expected = make_response({
        "2": [{
            "citizen_id": 1,
            "presents": 2
        }],
        "12": [{
            "citizen_id": 2,
            "presents": 1
        }, {
            "citizen_id": 3,
            "presents": 1
        }],
    })
    response = client.get(url)
    assert response.status_code == 200
    assert response.json()["data"] == expected
Exemplo n.º 2
0
def test_import():
    dataset = [
        generate_citizen(citizen_id=1, relatives=[2, 3]),
        generate_citizen(citizen_id=2, relatives=[1]),
        generate_citizen(citizen_id=3, relatives=[1]),
        generate_citizen(citizen_id=4, relatives=[]),
        generate_citizen(citizen_id=5,
                         name="Джейн",
                         gender="male",
                         birth_date="2020-02-17",
                         relatives=[5]),
    ]
    import_obj = Import(data=dataset)
    for i, citizen in enumerate(dataset):
        for k, v in citizen.items():
            value = getattr(import_obj.data[i], k)
            if isinstance(value, date):
                value = value.strftime("%Y-%m-%d")
            assert v == value

    with pytest.raises(ValidationError):
        dataset = [
            generate_citizen(citizen_id=1),
            generate_citizen(citizen_id=1),
        ]
        Import(data=dataset)

    with pytest.raises(ValidationError):
        dataset = [
            generate_citizen(citizen_id=1, relatives=[2, 3]),
            generate_citizen(citizen_id=2, relatives=[1]),
            generate_citizen(citizen_id=3, relatives=[]),
        ]
        Import(data=dataset)
Exemplo n.º 3
0
def test_no_relatives(migrated_postgres, client):
    dataset = [
        generate_citizen(citizen_id=1, birth_date="2019-12-31", relatives=[]),
        generate_citizen(citizen_id=2, birth_date="2020-02-11", relatives=[]),
        generate_citizen(citizen_id=3, birth_date="2020-02-17", relatives=[]),
    ]
    r = client.post("/imports", json={"data": dataset})
    import_id = r.json()["data"]["import_id"]
    url = f"/imports/{import_id}/citizens/birthdays"

    expected = make_response()
    response = client.get(url)
    assert response.status_code == 200
    assert response.json()["data"] == expected
async def test_patch_self_relative(database, migrated_postgres):
    """
    Проверяем что жителю можно указать себя родственником.
    """
    dataset = [
        generate_citizen(citizen_id=1,
                         name="Джейн",
                         gender="male",
                         birth_date="1945-03-13",
                         town="Нью-Йорк",
                         relatives=[]),
    ]
    dataset_import = Import(data=dataset)
    async with database:
        import_id = await analyzer.save_import(dataset_import, database)

    dataset[0]["relatives"] = [dataset[0]["citizen_id"]]
    data = {k: v for k, v in dataset[0].items() if k != "citizen_id"}
    patch = CitizenPatch(**data)
    async with database:
        actual = await analyzer.patch_citizen(import_id,
                                              dataset[0]["citizen_id"], patch,
                                              database)
    del actual["import_id"]
    assert compare_citizens(dataset[0], actual)
Exemplo n.º 5
0
def test_wrong_patch(migrated_postgres, client):
    citizen = generate_citizen(citizen_id=1)
    r = client.post("/imports", json={"data": [citizen]})
    import_id = r.json()["data"]["import_id"]
    url = f"/imports/{import_id}/citizens/1"
    patch = {
        "birth_date": (date.today() + timedelta(days=1)).strftime("%Y-%m-%d")
    }
    citizen.update(patch)
    response = client.patch(url, data=json.dumps(patch))
    assert response.status_code == 400
async def test_get_birthdays(database, migrated_postgres, dataset):
    # Перед прогоном каждого теста добавляем в БД дополнительную выгрузку с
    # двумя родственниками, чтобы убедиться, что обработчик различает жителей
    # разных выгрузок.
    import_obj = Import(data=[
        generate_citizen(citizen_id=1, relatives=[2]),
        generate_citizen(citizen_id=2, relatives=[1])
    ])
    async with database:
        await analyzer.save_import(import_obj, database)
        # Проверяем обработчик на указанных данных
        import_id = await analyzer.save_import(
            Import(data=dataset["citizens"]), database)
        result = await analyzer.get_birthdays(import_id, database)

    for month in dataset["expected"]:
        actual = {(citizen["citizen_id"], citizen["presents"])
                  for citizen in result[month]}
        expected = {(citizen["citizen_id"], citizen["presents"])
                    for citizen in dataset["expected"][month]}
        assert actual == expected
Exemplo n.º 7
0
def test_successful_patch(migrated_postgres, client):
    dataset = [
        generate_citizen(
            citizen_id=1,
            name="Иванов Иван Иванович",
            gender="male",
            birth_date="2020-01-01",
            town="Некий город",
            street="Некая улица",
            building="Некое строение",
            apartment=1,
            relatives=[2],
        ),
        generate_citizen(citizen_id=2, relatives=[1]),
        generate_citizen(citizen_id=3, relatives=[]),
    ]
    r = client.post("/imports", json={"data": dataset})
    import_id = r.json()["data"]["import_id"]
    url = f"/imports/{import_id}/citizens/1"

    dataset[0]["name"] = "Сидорова Василиса Петровна"
    patch = {"name": dataset[0]["name"]}
    response = client.patch(url, data=json.dumps(patch))
    assert response.status_code == 200
    assert response.json() == dataset[0]

    dataset[0]["gender"] = "female"
    dataset[0]["birth_date"] = "2020-01-02"
    dataset[0]["town"] = "Другой город"
    dataset[0]["street"] = "Другая улица"
    dataset[0]["building"] = "Другое строение"
    dataset[0]["apartment"] = 2
    dataset[0]["relatives"] = [3]
    patch = dataset[0].copy()
    patch.pop("citizen_id")
    response = client.patch(url, data=json.dumps(patch))
    assert response.status_code == 200
    assert response.json() == dataset[0]
Exemplo n.º 8
0
def test_self_relative(migrated_postgres, client):
    dataset = [
        generate_citizen(citizen_id=1,
                         name="Джейн",
                         gender="male",
                         birth_date="2020-02-17",
                         relatives=[1])
    ]
    r = client.post("/imports", json={"data": dataset})
    import_id = r.json()["data"]["import_id"]
    url = f"/imports/{import_id}/citizens/birthdays"

    expected = make_response({"2": [{"citizen_id": 1, "presents": 1}]})
    response = client.get(url)
    assert response.status_code == 200
    assert response.json()["data"] == expected
Exemplo n.º 9
0
async def test_get_ages(database, migrated_postgres, dataset):
    # Перед прогоном каждого теста добавим в БД дополнительную выгрузку с
    # жителем из другого города, чтобы убедиться, что обработчик различает
    # жителей разных выгрузок.
    import_obj = Import(
        data=[generate_citizen(citizen_id=1, town="Санкт-Петербург")])
    async with database:
        await analyzer.save_import(import_obj, database)
        import_id = await analyzer.save_import(
            Import(data=dataset["citizens"]), database)
        result = await analyzer.get_age_statistics(import_id, database)

    assert len(dataset["expected"]) == len(result), "Towns number is different"
    actual_towns_map = {town["town"]: town for town in result}

    for town in dataset["expected"]:
        assert town["town"] in actual_towns_map
        actual_town = actual_towns_map[town["town"]]

        for percentile in ["p50", "p75", "p99"]:
            assert town[percentile] == actual_town[percentile], (
                f"{town['town']} {percentile} {actual_town[percentile]} does "
                f"not match expected value {town[percentile]}")
def test_non_unique_ids(migrated_postgres, client):
    body = {"data": [generate_citizen(citizen_id=1), generate_citizen(citizen_id=1),]}
    response = client.post("/imports", json=body)
    assert response.status_code == 400
def test_wrong_dates(migrated_postgres, client):
    body = {"data": [generate_citizen(birth_date=(date.today() + timedelta(days=1)).strftime("%Y-%m-%d"))]}
    response = client.post("/imports", json=body)
    assert response.status_code == 400
import pytest
from utils import LONGEST_STR, MAX_INT, compare_citizen_groups, generate_citizen, generate_citizens

dataset = [
    generate_citizen(citizen_id=1, relatives=[2, 3]),
    generate_citizen(citizen_id=2, relatives=[1]),
    generate_citizen(citizen_id=3, relatives=[1]),
    generate_citizen(citizen_id=4, relatives=[]),
    generate_citizen(citizen_id=5,
                     name="Джейн",
                     gender="male",
                     birth_date="2020-02-17",
                     relatives=[5]),
]


def test_get_citizens(migrated_postgres, client):
    r = client.post("/imports", json={"data": dataset})
    import_id = r.json()["data"]["import_id"]

    response = client.get(f"/imports/{import_id}/citizens")
    assert response.status_code == 200
    assert compare_citizen_groups(response.json()["data"], dataset)
    Позволяет записать ожидаемый ответ в краткой форме.
    """
    return {
        str(month): values.get(str(month), []) if values else []
        for month in range(1, 13)
    }


datasets = [
    # Житель, у которого несколько родственников.
    # Обработчик должен корректно показывать сколько подарков приобретет
    # житель #1 своим родственникам в каждом месяце.
    {
        "citizens": [
            generate_citizen(citizen_id=1,
                             birth_date="2019-12-31",
                             relatives=[2, 3]),
            generate_citizen(citizen_id=2,
                             birth_date="2020-02-11",
                             relatives=[1]),
            generate_citizen(citizen_id=3,
                             birth_date="2020-02-17",
                             relatives=[1]),
        ],
        "expected":
        make_response({
            "2": [{
                "citizen_id": 1,
                "presents": 2
            }],
            "12": [{
Exemplo n.º 14
0
async def test_patch_citizen(database, migrated_postgres):
    """
    Проверяет, что данные о жителе и его родственниках успешно обновляются.
    """

    # Перед прогоном каждого теста добавляем в БД дополнительную выгрузку с
    # тремя жителями и одинаковыми идентификаторами, чтобы убедиться, что
    # обработчик различает жителей разных выгрузок и изменения не затронут
    # жителей другой выгрузки.
    side_dataset = [
        generate_citizen(citizen_id=1),
        generate_citizen(citizen_id=2),
        generate_citizen(citizen_id=3)
    ]
    side_import = Import(data=side_dataset)
    async with database:
        side_dataset_id = await analyzer.save_import(side_import, database)

    # Создаем выгрузку с тремя жителями, два из которых родственники для
    # тестирования изменений.
    dataset = [
        generate_citizen(
            citizen_id=1,
            name="Иванов Иван Иванович",
            gender="male",
            birth_date="2020-01-01",
            town="Некий город",
            street="Некая улица",
            building="Некое строение",
            apartment=1,
            relatives=[2],
        ),
        generate_citizen(citizen_id=2, relatives=[1]),
        generate_citizen(citizen_id=3, relatives=[]),
    ]
    import_obj = Import(data=dataset)
    async with database:
        import_id = await analyzer.save_import(import_obj, database)

    # Обновляем часть полей о жителе, чтобы убедиться что PATCH позволяет
    # передавать только некоторые поля.
    # Данные меняем сразу в выгрузке, чтобы потом было легче сравнивать.
    dataset[0]["name"] = "Иванова Иванна Ивановна"
    patch = CitizenPatch(name=dataset[0]["name"])
    async with database:
        await analyzer.patch_citizen(import_id, dataset[0]["citizen_id"],
                                     patch, database)

    # Обновляем другую часть данных, чтобы проверить что данные обновляются.
    dataset[0]["gender"] = "female"
    dataset[0]["birth_date"] = "2020-02-02"
    dataset[0]["town"] = "Другой город"
    dataset[0]["street"] = "Другая улица"
    dataset[0]["building"] = "Другое строение"
    dataset[0]["apartment"] += 1
    # У жителя #1 одна родственная связь должна исчезнуть (с жителем #2),
    # и одна появиться (с жителем #3).
    dataset[0]["relatives"] = [dataset[2]["citizen_id"]]
    # Родственные связи должны быть двусторонними:
    # - у жителя #2 родственная связь с жителем #1 удаляется
    # - у жителя #3 родственная связь с жителем #1 добавляется.
    dataset[2]["relatives"].append(dataset[0]["citizen_id"])
    dataset[1]["relatives"].remove(dataset[0]["citizen_id"])

    patch = CitizenPatch.parse_obj({
        "gender": dataset[0]["gender"],
        "birth_date": dataset[0]["birth_date"],
        "town": dataset[0]["town"],
        "street": dataset[0]["street"],
        "building": dataset[0]["building"],
        "apartment": dataset[0]["apartment"],
        "relatives": dataset[0]["relatives"],
    })
    async with database:
        actual = await analyzer.patch_citizen(import_id,
                                              dataset[0]["citizen_id"], patch,
                                              database)

    # Проверяем, что житель корректно обновился
    del actual["import_id"]
    assert compare_citizens(dataset[0], actual)

    # Проверяем всю выгрузку, чтобы убедиться что родственные связи всех
    # жителей изменились корректно.
    async with database:
        actual_citizens = await analyzer.get_citizens(import_id, database)
    for citizen in actual_citizens:
        del citizen["import_id"]
    assert compare_citizen_groups(actual_citizens, dataset)

    # Проверяем, что изменение жителя в тестируемой выгрузке не испортило
    # данные в дополнительной выгрузке.
    async with database:
        actual_citizens = await analyzer.get_citizens(side_dataset_id,
                                                      database)
    for citizen in actual_citizens:
        del citizen["import_id"]
    assert compare_citizen_groups(actual_citizens, side_dataset)
Exemplo n.º 15
0
    и days дней. Позволяет представлять дату рождения жителя в виде возраста человека в днях
    и годах, что гораздо нагляднее в тестах.
    """
    _today = date.today()
    birth_date = _today.replace(year=_today.year - years)
    birth_date -= timedelta(days=days)
    return birth_date.strftime("%Y-%m-%d")


datasets = [
    # Несколько жителей у которых завтра день рождения.
    # Проверяется что обработчик использует в рассчетах количество полных лет.
    {
        "citizens": [
            generate_citizen(birth_date=age2date(years=10, days=364),
                             town="Москва",
                             citizen_id=1),
            generate_citizen(birth_date=age2date(years=30, days=364),
                             town="Москва",
                             citizen_id=2),
            generate_citizen(birth_date=age2date(years=50, days=364),
                             town="Москва",
                             citizen_id=3),
        ],
        "expected": [{
            "town": "Москва",
            "p50": 30.0,
            "p75": 40.0,
            "p99": 49.6
        }],
    },