Files
notifications-admin/tests/app/broadcast_areas/test_broadcast_area.py
Chris Hill-Scott 8a413bec91 Merge pull request #3617 from alphagov/population-estimates
Give estimates of the number of phones in a broadcast area
2020-09-17 11:41:00 +01:00

266 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import pytest
from app.broadcast_areas import (
BroadcastAreasRepository,
broadcast_area_libraries,
)
from app.broadcast_areas.populations import (
CITY_OF_LONDON,
estimate_number_of_smartphones_for_population,
)
def test_loads_libraries():
assert [
(library.id, library.name, library.is_group) for library in sorted(broadcast_area_libraries)
] == [
(
'ctry19',
'Countries',
False,
),
(
'wd20-lad20-ctyua19',
'Local authorities',
True,
),
]
def test_loads_areas_from_library():
assert [
(area.id, area.name) for area in sorted(
broadcast_area_libraries.get('ctry19')
)
] == [
('ctry19-E92000001', 'England'),
('ctry19-N92000002', 'Northern Ireland'),
('ctry19-S92000003', 'Scotland'),
('ctry19-W92000004', 'Wales'),
]
def test_examples():
countries = broadcast_area_libraries.get('ctry19').get_examples()
assert countries == 'England, Northern Ireland, Scotland and Wales'
wards = broadcast_area_libraries.get('wd20-lad20-ctyua19').get_examples()
assert wards == 'Aberdeen City, Aberdeenshire, Adur and 391 more…'
@pytest.mark.parametrize('id', (
'ctry19-E92000001',
'ctry19-N92000002',
'ctry19-S92000003',
'ctry19-W92000004',
pytest.param('mercia', marks=pytest.mark.xfail(raises=KeyError)),
))
def test_loads_areas_from_libraries(id):
assert (
broadcast_area_libraries.get('ctry19').get(id)
) == (
broadcast_area_libraries.get_areas(id)[0]
)
def test_get_names_of_areas():
areas = broadcast_area_libraries.get_areas(
'ctry19-W92000004',
'lad20-W06000014',
'ctry19-E92000001',
)
assert [area.name for area in sorted(areas)] == [
'England', 'Vale of Glamorgan', 'Wales',
]
def test_get_areas_accepts_lists():
areas_from_list = broadcast_area_libraries.get_areas(
[
'ctry19-W92000004',
'ctry19-E92000001',
]
)
areas_from_args = broadcast_area_libraries.get_areas(
'ctry19-W92000004',
'ctry19-E92000001',
)
assert len(areas_from_args) == len(areas_from_list) == 2
assert areas_from_args == areas_from_list
def test_has_polygons():
england = broadcast_area_libraries.get_areas('ctry19-E92000001')[0]
scotland = broadcast_area_libraries.get_areas('ctry19-S92000003')[0]
assert len(england.polygons) == 35
assert len(scotland.polygons) == 195
assert england.polygons.as_coordinate_pairs_lat_long[0][0] == [
55.811085, -2.034358 # https://goo.gl/maps/wsf2LUWzYinwydMk8
]
def test_polygons_are_enclosed():
england = broadcast_area_libraries.get('ctry19').get('ctry19-E92000001')
first_polygon = england.polygons.as_coordinate_pairs_lat_long[0]
assert first_polygon[0] != first_polygon[1] != first_polygon[2]
assert first_polygon[0] == first_polygon[-1]
def test_lat_long_order():
england = broadcast_area_libraries.get_areas('ctry19-E92000001')[0]
lat_long = england.polygons.as_coordinate_pairs_lat_long
long_lat = england.polygons.as_coordinate_pairs_long_lat
assert len(lat_long[0]) == len(long_lat[0]) == 2082 # Coordinates in polygon
assert len(lat_long[0][0]) == len(long_lat[0][0]) == 2 # Axes in coordinates
assert lat_long[0][0] == list(reversed(long_lat[0][0]))
def test_includes_electoral_wards():
areas = broadcast_area_libraries.get_areas(['wd20-E05009289'])
assert len(areas) == 1
def test_electoral_wards_are_groupable_cardiff():
areas = broadcast_area_libraries.get_areas(['lad20-W06000015'])
assert len(areas) == 1
cardiff = areas[0]
assert len(cardiff.sub_areas) == 29
def test_electoral_wards_are_groupable_ealing():
areas = broadcast_area_libraries.get_areas(['lad20-E09000009'])
assert len(areas) == 1
ealing = areas[0]
assert len(ealing.sub_areas) == 23
def test_repository_has_all_libraries():
repo = BroadcastAreasRepository()
libraries = repo.get_libraries()
assert len(libraries) == 2
assert [
('Countries', 'country'),
('Local authorities', 'local authority'),
] == [(name, name_singular) for _, name, name_singular, _is_group in libraries]
@pytest.mark.parametrize('library', (
broadcast_area_libraries
))
def test_every_area_has_count_of_phones(library):
for area in library:
assert area.count_of_phones > 0
@pytest.mark.parametrize('area_id, area_name, expected_count', (
# Unitary authority
('ctyua19-E10000014', 'Hampshire', 853_594.48),
# District
('lad20-E07000087', 'Fareham', 81_970.06),
# Ward
('wd20-E05004516', 'Fareham East', 5_684.9),
# Unitary authority
('lad20-E09000012', 'Hackney', 222_578.0),
# Ward
('wd20-E05009373', 'Hackney Downs', 11_321.169999999998),
# Special case: ward with hard-coded population
('wd20-E05011090', 'Bryher', 76.44),
# Areas with missing data
('lad20-E07000008', 'Cambridge', 0),
('lad20-E07000084', 'Basingstoke and Deane', 0),
('lad20-E07000118', 'Chorley', 0),
('lad20-E07000178', 'Oxford', 0),
))
def test_count_of_phones_for_all_levels(area_id, area_name, expected_count):
area = broadcast_area_libraries.get_areas(area_id)[0]
assert area.name == area_name
assert area.count_of_phones == expected_count
def test_city_of_london_counts_are_not_derived_from_population():
city_of_london = broadcast_area_libraries.get_areas('lad20-E09000001')[0]
assert city_of_london.name == 'City of London'
assert len(city_of_london.sub_areas) == len(CITY_OF_LONDON.WARDS) == 25
for ward in city_of_london.sub_areas:
# The population of the whole City of London is 9,401, so an
# average of 300 per ward. What were asserting here is that the
# count of phones is much larger, because it isnt derived from
# the resident population.
assert ward.count_of_phones > 5_000
@pytest.mark.parametrize('population, expected_estimate', (
# Upper and lower bounds of each age range
(
[(0, 100)], 50,
),
(
[(16, 100)], 100
),
(
[(24, 100)], 100,
),
(
[(25, 100)], 97,
),
(
[(34, 100)], 97,
),
(
[(35, 100)], 91
),
(
[(44, 100)], 91,
),
(
[(45, 100)], 88
),
(
[(54, 100)], 88,
),
(
[(55, 100)], 73
),
(
[(64, 100)], 73,
),
(
[(65, 100)], 40
),
(
[(999, 100)], 40,
),
# Multiple different ages in a single popualtion
(
[(16, 100), (54, 100)], 188
),
(
[(1, 1000), (66, 100)], 540
),
))
def test_estimate_number_of_smartphones_for_population(
population, expected_estimate,
):
assert estimate_number_of_smartphones_for_population(
population
) == expected_estimate