Pytest adoption tracker
Iris approximate pytest adoption
Generated using this script
Click to expand this section...
import ast
from pathlib import Path
from sys import argv
# Also requires the `tabulate` package.
import pandas as pd
if not (len(argv) == 2 and Path(argv[1]).exists()):
message = "Correct script usage = `pytest_adoption.py <iris_root_dir>`"
raise ValueError(message)
IRIS_ROOT = Path(argv[1])
IRIS_TREE_URL = "https://github.com/SciTools/iris/tree/main/"
markdown_path = Path(__file__).with_suffix(".md")
tests_dir = IRIS_ROOT / "lib" / "iris" / "tests"
dataframe_data = []
total_asserts = 0
total_asserts_pytest = 0
for file_path in tests_dir.rglob("*.py"):
file_text = file_path.read_text()
parsed = ast.parse(source=file_text)
calls = filter(lambda node: hasattr(node, "func"), ast.walk(parsed))
assert_calls = filter(
lambda c: getattr(c.func, "attr", "")[:6] == "assert", calls
)
assert_calls_methods = filter(lambda c: hasattr(c.func, "value"), assert_calls)
assert_calls_methods_self = filter(
lambda m: getattr(m.func.value, "id", "") == "self", assert_calls_methods
)
num_asserts_unittest = len(list(assert_calls_methods_self))
assert_keywords = filter(
lambda node: isinstance(node, ast.Assert), ast.walk(parsed)
)
num_asserts_pytest = len(list(assert_keywords))
both_asserts = num_asserts_unittest + num_asserts_pytest
if both_asserts == 0:
percent_adoption = "N/A"
else:
percent_adoption = f"{num_asserts_pytest / both_asserts * 100:.0f}"
total_asserts += both_asserts
total_asserts_pytest += num_asserts_pytest
file_url = IRIS_TREE_URL + str(file_path.relative_to(IRIS_ROOT))
file_link_text = f"{file_path.relative_to(tests_dir).stem}"
dataframe_data.append(
{
"% adoption": percent_adoption,
# "File Path": f"[{file_link_text}]({file_url})",
"File Path": f"{file_link_text}",
"Number of `self.assertSomething()`": num_asserts_unittest,
"Number of `assert something`": num_asserts_pytest,
}
)
pytest_adoption_df = pd.DataFrame(dataframe_data)
total_percent_adoption = f"{total_asserts_pytest / total_asserts * 100:.0f}%"
total_line = (
"## Total adoption\n\n"
f"### {total_asserts_pytest} out of {total_asserts} : {total_percent_adoption}"
)
script_line = (
"## Generated using this script\n\n"
"<details>\n"
"<summary>Click to expand <b>this section...</b></summary>\n\n"
"```python\n"
f"{Path(__file__).read_text()}"
"```\n\n"
"</details>"
)
# pytest_adoption_df.to_markdown(markdown_path, index=False)
pytest_adoption_df.to_html(markdown_path, index=False)
full_text = (
"# Iris approximate pytest adoption\n\n"
f"{script_line}\n\n"
f"{total_line}\n\n"
"## Breakdown\n\n"
f"{markdown_path.read_text()}"
)
markdown_path.write_text(full_text)
Total adoption
548 out of 10272 : 5%
Breakdown
| % adoption | File Path | Number of `self.assertSomething()` | Number of `assert something` |
|---|---|---|---|
| 0 | test_nimrod | 6 | 0 |
| 0 | test_cube_to_pp | 15 | 0 |
| 0 | test_basic_maths | 152 | 0 |
| 0 | test_coord_api | 138 | 0 |
| N/A | test_imports | 0 | 0 |
| 0 | test_file_load | 5 | 0 |
| 0 | test_util | 29 | 0 |
| 0 | test_cube | 9 | 0 |
| 0 | test_file_save | 15 | 0 |
| 0 | test_hybrid | 45 | 0 |
| 0 | test_image_json | 4 | 0 |
| 0 | test_pp_to_cube | 15 | 0 |
| 100 | test_coding_standards | 0 | 4 |
| 0 | test_cell | 90 | 0 |
| 0 | test_peak | 29 | 0 |
| 0 | test_intersect | 2 | 0 |
| 0 | test_io_init | 6 | 0 |
| 0 | test_iterate | 74 | 0 |
| 0 | test_mapping | 3 | 0 |
| 0 | test_pp_module | 88 | 0 |
| 0 | system_test | 1 | 0 |
| 0 | test_aggregate_by | 62 | 0 |
| 65 | test_lazy_aggregate_by | 6 | 11 |
| 0 | test_pp_stash | 53 | 0 |
| 2 | test_merge | 100 | 2 |
| 0 | test_pickling | 15 | 0 |
| 0 | test_coordsystem | 90 | 0 |
| 0 | test_constraints | 119 | 0 |
| 0 | test_uri_callback | 1 | 0 |
| 20 | test_analysis | 166 | 41 |
| 0 | test_cf | 92 | 0 |
| 0 | test_concatenate | 161 | 0 |
| 0 | test_cartography | 3 | 0 |
| 0 | test_abf | 3 | 0 |
| 0 | test_plot | 24 | 0 |
| 0 | test_name | 9 | 0 |
| 0 | __init__ | 20 | 0 |
| 0 | test_cdm | 265 | 0 |
| 0 | test_ff | 42 | 0 |
| 0 | test_load | 21 | 0 |
| 0 | test_netcdf | 102 | 0 |
| 0 | test_analysis_calculus | 62 | 0 |
| 0 | test_pp_cf | 3 | 0 |
| 0 | test_quickplot | 7 | 0 |
| 0 | test_std_names | 5 | 0 |
| 0 | test_raster | 3 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 2 | test_regrid_area_weighted_rectilinear_src_and_grid | 54 | 1 |
| 0 | test_regrid_conservative_via_esmpy | 40 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | idiff | 0 | 0 |
| N/A | recreate_imagerepo | 0 | 0 |
| 0 | test_pp | 74 | 0 |
| 0 | test_regrid_equivalence | 8 | 0 |
| 0 | test_pp_constrained_load_cubes | 3 | 0 |
| 0 | test_Datums | 1 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_PartialDateTime | 1 | 0 |
| 0 | test_ff | 11 | 0 |
| 0 | test_new_axis | 3 | 0 |
| 0 | test_subset | 1 | 0 |
| 0 | test_cube | 5 | 0 |
| 100 | test_netcdf__loadsaveattrs | 0 | 23 |
| 0 | test_climatology | 3 | 0 |
| 0 | test_pickle | 1 | 0 |
| 0 | test_trajectory | 13 | 0 |
| 0 | test_regridding | 11 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_area_weighted | 4 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_OceanSigmaZFactory | 6 | 0 |
| N/A | __init__ | 0 | 0 |
| 14 | test_concatenate | 31 | 5 |
| N/A | __init__ | 0 | 0 |
| 0 | test_CubeRepresentation | 33 | 0 |
| 0 | test_regrid_ProjectedUnstructured | 13 | 0 |
| 0 | test_ugrid_load | 9 | 0 |
| 0 | test_ugrid_save | 5 | 0 |
| N/A | __init__ | 0 | 0 |
| 3 | test_fast_load | 28 | 1 |
| N/A | __init__ | 0 | 0 |
| 0 | test_merge | 3 | 0 |
| 100 | test_thread_safety | 0 | 7 |
| 100 | test_delayed_save | 0 | 36 |
| 0 | test_attributes | 5 | 0 |
| 12 | test_aux_factories | 7 | 1 |
| 5 | test_general | 39 | 2 |
| N/A | __init__ | 0 | 0 |
| 100 | test_self_referencing | 0 | 2 |
| 100 | test__dask_locks | 0 | 11 |
| 0 | test_coord_systems | 11 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_colorbar | 6 | 0 |
| N/A | test_animate | 0 | 0 |
| 0 | test_netcdftime | 1 | 0 |
| 0 | test_nzdateline | 1 | 0 |
| N/A | test_plot_2d_coords | 0 | 0 |
| 0 | test_vector_plots | 1 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_fieldsfile | 2 | 0 |
| 100 | _stock_2d_latlons | 0 | 2 |
| N/A | __init__ | 0 | 0 |
| N/A | mesh | 0 | 0 |
| 100 | netcdf | 0 | 1 |
| N/A | __init__ | 0 | 0 |
| N/A | conftest | 0 | 0 |
| 0 | test_Future | 14 | 0 |
| 0 | test_sample_data_path | 8 | 0 |
| 0 | test_VARIANCE | 12 | 0 |
| 0 | test_COUNT | 14 | 0 |
| 0 | test_Nearest | 5 | 0 |
| 0 | test_PROPORTION | 7 | 0 |
| 0 | test_PointInCell | 1 | 0 |
| 0 | test_STD_DEV | 9 | 0 |
| 0 | test_WPERCENTILE | 40 | 0 |
| 0 | test__axis_to_single_trailing | 8 | 0 |
| 0 | test_PercentileAggregator | 19 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Aggregator | 21 | 0 |
| 0 | test_MAX | 9 | 0 |
| 0 | test_MEAN | 11 | 0 |
| 0 | test_MIN | 9 | 0 |
| 0 | test_AreaWeighted | 4 | 0 |
| 0 | test_Linear | 5 | 0 |
| 0 | test_RMS | 18 | 0 |
| 0 | test_SUM | 27 | 0 |
| 0 | test_PERCENTILE | 32 | 0 |
| 0 | test_MAX_RUN | 6 | 0 |
| 0 | test_WeightedPercentileAggregator | 21 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_AreaWeightedRegridder | 20 | 0 |
| 0 | test_gridcell_angles | 31 | 0 |
| 0 | test_project | 15 | 0 |
| 0 | test_rotate_grid_vectors | 9 | 0 |
| 2 | test_rotate_winds | 65 | 1 |
| 100 | test__get_lon_lat_coords | 0 | 6 |
| 0 | test__quadrant_area | 9 | 0 |
| 60 | test__xy_range | 2 | 3 |
| N/A | __init__ | 0 | 0 |
| 0 | test_area_weights | 2 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_geometry_area_weights | 10 | 0 |
| 0 | test__extract_relevant_cube_slice | 5 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_RectilinearInterpolator | 65 | 0 |
| 0 | test_get_xy_dim_coords | 15 | 0 |
| N/A | test__arith__dask_array | 0 | 0 |
| 0 | test_divide | 4 | 0 |
| 0 | __init__ | 28 | 0 |
| 0 | test_add | 2 | 0 |
| 0 | test_multiply | 2 | 0 |
| 0 | test_subtract | 2 | 0 |
| N/A | test__arith__derived_coords | 0 | 0 |
| 6 | test__arith__meshcoords | 16 | 1 |
| 0 | test__get_dtype | 1 | 0 |
| 0 | test__inplace_common_checks | 21 | 0 |
| 0 | test__output_dtype | 8 | 0 |
| N/A | __init__ | 0 | 0 |
| 1 | test_RectilinearRegridder | 146 | 2 |
| 40 | test__CurvilinearRegridder | 12 | 8 |
| N/A | __init__ | 0 | 0 |
| 0 | test__RegularGridInterpolator | 8 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_pearsonr | 15 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_UnstructuredNearestNeighbourRegridder | 19 | 0 |
| 0 | test__nearest_neighbour_indices_ndcoords | 12 | 0 |
| 0 | test_Trajectory | 35 | 0 |
| 53 | test_interpolate | 14 | 16 |
| 31 | test_AtmosphereSigmaFactory | 18 | 8 |
| 0 | test_OceanSFactory | 32 | 0 |
| 0 | test_OceanSg1Factory | 31 | 0 |
| 0 | test_OceanSigmaFactory | 18 | 0 |
| 0 | test_AuxCoordFactory | 26 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_HybridPressureFactory | 32 | 0 |
| 0 | test_OceanSg2Factory | 31 | 0 |
| 0 | test_OceanSigmaZFactory | 43 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Lenient | 49 | 0 |
| 0 | test__Lenient | 120 | 0 |
| 0 | test__lenient_client | 36 | 0 |
| 0 | test__lenient_service | 20 | 0 |
| 0 | test__qualname | 5 | 0 |
| 0 | test_BaseMetadata | 284 | 0 |
| 0 | test_CoordMetadata | 113 | 0 |
| 0 | test__NamedTupleMeta | 23 | 0 |
| 0 | test_metadata_filter | 23 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_AncillaryVariableMetadata | 89 | 0 |
| 0 | test_CellMeasureMetadata | 113 | 0 |
| 54 | test_CubeMetadata | 50 | 59 |
| 0 | test_hexdigest | 26 | 0 |
| 0 | test_metadata_manager_factory | 23 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_CFVariableMixin | 50 | 0 |
| 0 | test_LimitedAttributeDict | 9 | 0 |
| 0 | test__get_valid_standard_name | 11 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Resolve | 546 | 0 |
| 100 | __init__ | 0 | 2 |
| 100 | test__CoordMetaData | 0 | 5 |
| 100 | test__CoordSignature | 0 | 4 |
| 0 | test__CubeSignature | 10 | 0 |
| 0 | test_concatenate | 49 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_NetCDF | 6 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Constraint_equality | 49 | 0 |
| 0 | test_NameConstraint | 48 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_add_categorised_coord | 2 | 0 |
| 0 | test_add_hour | 4 | 0 |
| 100 | test_coord_categorisation | 0 | 2 |
| 0 | test_Stereographic | 16 | 0 |
| 0 | test_TransverseMercator | 6 | 0 |
| 0 | test_Mercator | 18 | 0 |
| 0 | test_PolarStereographic | 23 | 0 |
| 0 | test_LambertAzimuthalEqualArea | 10 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_GeogCS | 5 | 0 |
| 0 | test_LambertConformal | 16 | 0 |
| 0 | test_Orthographic | 6 | 0 |
| N/A | test_RotatedMercator | 0 | 0 |
| 0 | test_RotatedPole | 8 | 0 |
| 0 | test_Geostationary | 8 | 0 |
| 100 | test_ObliqueMercator | 0 | 1 |
| 0 | test_VerticalPerspective | 6 | 0 |
| 0 | test_AlbersEqualArea | 18 | 0 |
| 0 | test_DimCoord | 85 | 0 |
| 0 | test__DimensionalMetadata | 51 | 0 |
| 0 | test_CellMethod | 6 | 0 |
| 0 | test_AncillaryVariable | 70 | 0 |
| 0 | test_CellMeasure | 18 | 0 |
| 2 | test_Coord | 146 | 3 |
| 0 | __init__ | 15 | 0 |
| 0 | test_AuxCoord | 118 | 0 |
| 0 | test_Cell | 39 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Cube__operators | 10 | 0 |
| 100 | test_CubeAttrsDict | 0 | 45 |
| 3 | test_CubeList | 64 | 2 |
| 4 | test_Cube__aggregated_by | 112 | 5 |
| 5 | test_Cube | 497 | 27 |
| N/A | __init__ | 0 | 0 |
| 0 | test_DataManager | 141 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_export_geotiff | 7 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_regrid_area_weighted_rectilinear_src_and_grid | 11 | 0 |
| 0 | test_regrid_weighted_curvilinear_to_rectilinear | 18 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_CubeListRepresentation | 5 | 0 |
| 0 | test_CubeRepresentation | 57 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_relevel | 6 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 20 | test_CFUGridAuxiliaryCoordinateVariable | 8 | 2 |
| 20 | test_CFUGridConnectivityVariable | 8 | 2 |
| 0 | test_CFUGridGroup | 5 | 0 |
| 17 | test_CFUGridMeshVariable | 10 | 2 |
| 0 | test_CFUGridReader | 5 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_ParseUgridOnLoad | 8 | 0 |
| 0 | test_load_mesh | 3 | 0 |
| 0 | test_load_meshes | 20 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Connectivity | 43 | 0 |
| 0 | test_Mesh | 147 | 0 |
| 2 | test_MeshCoord | 100 | 2 |
| 0 | test_Mesh__from_coords | 41 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_ConnectivityMetadata | 121 | 0 |
| 0 | test_MeshCoordMetadata | 113 | 0 |
| 0 | test_MeshMetadata | 121 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_recombine_submeshes | 49 | 0 |
| 0 | __init__ | 6 | 0 |
| 7 | test_rules | 28 | 2 |
| N/A | __init__ | 0 | 0 |
| 0 | test_ABFField | 2 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_CFGroup | 1 | 0 |
| 0 | test_CFReader | 48 | 0 |
| N/A | __init__ | 0 | 0 |
| 50 | test__dot_path | 4 | 4 |
| N/A | __init__ | 0 | 0 |
| 0 | test_ArakawaC | 6 | 0 |
| 0 | test_Grid | 10 | 0 |
| 0 | test_NewDynamics | 3 | 0 |
| 0 | test_ENDGame | 3 | 0 |
| 0 | test_FFHeader | 7 | 0 |
| 0 | test_FF2PP | 32 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__cf_height_from_name | 23 | 0 |
| 0 | test__build_cell_methods | 7 | 0 |
| 0 | test__build_lat_lon_for_NAME_timeseries | 18 | 0 |
| 0 | test__calc_integration_period | 7 | 0 |
| 0 | test__generate_cubes | 22 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__grid_mappings | 22 | 0 |
| 0 | test__hybrid_formulae | 3 | 0 |
| 27 | test__latlon_dimcoords | 8 | 3 |
| 0 | test__miscellaneous | 20 | 0 |
| 20 | test__time_coords | 16 | 4 |
| 0 | __init__ | 2 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_engine | 17 | 0 |
| 0 | test_build_cube_metadata | 6 | 0 |
| 43 | test_build_dimension_coordinate | 8 | 6 |
| 0 | test_build_geostationary_coordinate_system | 1 | 0 |
| 0 | test_build_lambert_conformal_coordinate_system | 1 | 0 |
| 0 | test_build_stereographic_coordinate_system | 1 | 0 |
| 0 | test_build_transverse_mercator_coordinate_system | 1 | 0 |
| 0 | test_build_verticalp_coordinate_system | 1 | 0 |
| 0 | test_get_attr_units | 2 | 0 |
| 0 | test_get_cf_bounds_var | 2 | 0 |
| 0 | test_has_supported_mercator_parameters | 7 | 0 |
| 0 | test_reorder_bounds_data | 3 | 0 |
| 0 | test_build_polar_stereographic_coordinate_system | 5 | 0 |
| 0 | test_get_names | 4 | 0 |
| 0 | test_has_supported_polar_stereographic_parameters | 15 | 0 |
| 100 | test_build_ancil_var | 0 | 1 |
| 100 | test_build_cell_measure | 0 | 1 |
| N/A | test_build_oblique_mercator_coordinate_system | 0 | 0 |
| 0 | test_parse_cell_methods | 12 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_build_albers_equal_area_coordinate_system | 1 | 0 |
| 20 | test_build_auxiliary_coordinate | 4 | 1 |
| 0 | test_build_lambert_azimuthal_equal_area_coordinate_system | 1 | 0 |
| 0 | test_build_mercator_coordinate_system | 5 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__load_cube | 12 | 0 |
| 0 | test__get_cf_var_data | 9 | 0 |
| 0 | test__load_aux_factory | 40 | 0 |
| 0 | test__translate_constraints_to_var_callback | 10 | 0 |
| 0 | test_load_cubes | 28 | 0 |
| 100 | test__chunk_control | 0 | 37 |
| 0 | test__data_fillvalue_check | 11 | 0 |
| 100 | test__fillvalue_report | 0 | 5 |
| 0 | test_Saver__ugrid | 121 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_Saver__lazy | 4 | 0 |
| 0 | test_Saver | 67 | 0 |
| 100 | test_Saver__lazy_stream_data | 0 | 12 |
| 16 | test_save | 21 | 4 |
| N/A | __init__ | 0 | 0 |
| 0 | test_vertical_coord | 2 | 0 |
| 0 | test_units | 36 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_PPDataProxy | 9 | 0 |
| 0 | test__create_field_data | 3 | 0 |
| 0 | test__field_gen | 7 | 0 |
| 0 | test_as_fields | 2 | 0 |
| N/A | test_load | 0 | 0 |
| 0 | test_save_fields | 4 | 0 |
| 0 | test_save_pairs_from_cube | 6 | 0 |
| 0 | test_PPField | 58 | 0 |
| 0 | test__convert_constraints | 13 | 0 |
| 0 | test__interpret_field | 14 | 0 |
| 16 | test_save | 31 | 6 |
| 12 | test__data_bytes_to_shaped_array | 7 | 1 |
| 0 | test__convert_scalar_pseudo_level_coords | 2 | 0 |
| 0 | test__convert_time_coords | 19 | 0 |
| 0 | test__convert_vertical_coords | 18 | 0 |
| 0 | test__reshape_vector_args | 6 | 0 |
| 0 | test__model_level_number | 2 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__dim_or_aux | 2 | 0 |
| 0 | test_convert | 13 | 0 |
| 0 | test__collapse_degenerate_points_and_bounds | 16 | 0 |
| 0 | test__convert_scalar_realization_coords | 2 | 0 |
| 0 | test__epoch_date_hours | 14 | 0 |
| 0 | test__reduced_points_and_bounds | 23 | 0 |
| 0 | test__all_other_rules | 17 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__make_cube | 3 | 0 |
| 0 | test_Loader | 8 | 0 |
| N/A | __init__ | 0 | 0 |
| 3 | test_ArrayStructure | 31 | 1 |
| 0 | test_GroupStructure | 18 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_um_to_pp | 3 | 0 |
| 0 | test__convert_collation | 25 | 0 |
| 0 | test_FieldCollation | 7 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_BasicFieldCollation | 28 | 0 |
| 10 | test_group_structured_fields | 9 | 1 |
| N/A | __init__ | 0 | 0 |
| 0 | test_optimal_array_structure | 32 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_expand_filespecs | 11 | 0 |
| 0 | test_run_callback | 8 | 0 |
| N/A | test__generate_cubes | 0 | 0 |
| N/A | test_save | 0 | 0 |
| 0 | test_co_realise_cubes | 7 | 0 |
| 0 | test_is_lazy_data | 2 | 0 |
| 100 | test_is_lazy_masked_data | 0 | 1 |
| 0 | test_lazy_elementwise | 8 | 0 |
| 0 | test_multidim_lazy_stack | 3 | 0 |
| 0 | test_non_lazy | 4 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_as_concrete_data | 17 | 0 |
| 0 | test_as_lazy_data | 13 | 0 |
| 0 | test_map_complete_blocks | 12 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_ProtoCube | 9 | 0 |
| N/A | __init__ | 0 | 0 |
| 37 | test_pandas | 80 | 46 |
| 0 | test__fixup_dates | 7 | 0 |
| 0 | test__get_plot_objects | 3 | 0 |
| 0 | test_contour | 5 | 0 |
| 0 | test_contourf | 5 | 0 |
| 100 | test_hist | 0 | 1 |
| 0 | test_outline | 5 | 0 |
| N/A | test_pcolor | 0 | 0 |
| N/A | test_pcolormesh | 0 | 0 |
| 0 | test_points | 5 | 0 |
| 0 | _blockplot_common | 7 | 0 |
| 0 | test__get_plot_defn | 3 | 0 |
| 0 | test__replace_axes_with_cartopy_axes | 2 | 0 |
| 0 | test_scatter | 4 | 0 |
| 0 | __init__ | 6 | 0 |
| 0 | test__check_bounds_contiguity_and_mask | 2 | 0 |
| 0 | test__check_geostationary_coords_and_convert | 1 | 0 |
| 0 | test__get_plot_defn_custom_coords_picked | 13 | 0 |
| 0 | test_plot | 8 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_contour | 2 | 0 |
| 0 | test_contourf | 2 | 0 |
| 0 | test_outline | 2 | 0 |
| 0 | test_plot | 6 | 0 |
| 0 | test_points | 2 | 0 |
| 0 | test_scatter | 2 | 0 |
| 0 | test_pcolor | 2 | 0 |
| 0 | test_pcolormesh | 2 | 0 |
| N/A | __init__ | 0 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_CubePrintout | 37 | 0 |
| 0 | test_Table | 34 | 0 |
| N/A | __init__ | 0 | 0 |
| 2 | test_CubeSummary | 63 | 1 |
| N/A | __init__ | 0 | 0 |
| 0 | test_IrisTest | 14 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_netcdf | 9 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test_PartialDateTime | 16 | 0 |
| 0 | test_demote_dim_coord_to_aux_coord | 7 | 0 |
| 0 | test_describe_diff | 3 | 0 |
| 100 | test_guess_coord_axis | 0 | 3 |
| 0 | test_squeeze | 5 | 0 |
| 100 | test_new_axis | 0 | 26 |
| 0 | test_reverse | 38 | 0 |
| 0 | test_rolling_window | 9 | 0 |
| 0 | test__slice_data_with_keys | 10 | 0 |
| 100 | test__mask_array | 0 | 11 |
| 0 | test_mask_cube | 17 | 0 |
| 0 | test_file_is_newer_than | 8 | 0 |
| N/A | __init__ | 0 | 0 |
| 0 | test__is_circular | 2 | 0 |
| 0 | test_array_equal | 29 | 0 |
| 0 | test_column_slices_generator | 2 | 0 |
| 0 | test_broadcast_to_shape | 7 | 0 |
| 0 | test_promote_aux_coord_to_dim_coord | 11 | 0 |
| 60 | test_unify_time_units | 2 | 3 |
| 0 | test__coord_regular | 17 | 0 |
| 0 | test_find_discontiguities | 7 | 0 |
| 64 | test_equalise_attributes | 5 | 9 |
Sorry for the janky formatting - reached the character limit. But it's here as a proof of concept that could be automated.
Ping @ESadek-MO
Hi @trexfeathers Nice work, but a couple of things bothering me :
Firstly, it would be much handier to have a full path to each test module in the table Was this due to the line-length constraint you mention ?
Secondly, I think the entry for test_netcdf__loadsaveattrs is showing some problems :
It is saying
| %pytest | name | N-unittest | N-pytest |
|---|---|---|---|
| 15 | test_netcdf__loadsaveattrs | 127 | 23 |
But actually, this module is entirely written in pytest. So something odd here ?
@pp-mo
Firstly, it would be much handier to have a full path to each test module in the table Was this due to the line-length constraint you mention ?
100% - I did originally have the full path and it was even a link.
Secondly, I think the entry for
test_netcdf__loadsaveattrsis showing some problems : It is saying%pytest name N-unittest N-pytest 15 test_netcdf__loadsaveattrs 127 23 But actually, this module is entirely written in pytest. So something odd here ?
Good spot! That was copy-pasta. I have updated
-assert_calls_methods = filter(lambda c: hasattr(c.func, "value"), calls)
+assert_calls_methods = filter(lambda c: hasattr(c.func, "value"), assert_calls)
pytestify is excellent, so if you can get a given test module to a point where it is using unittest.TestCase rather than a bespoke Iris test class, the rest should be is easy.
Apologies if I'm teaching Granny to suck eggs.
if you can get a given test module to a point where it is using
unittest.TestCaserather than a bespoke Iris test class, the rest should be is easy
I may have misunderstood. If I've understood correctly, then I don't think this is realistic. The use of IrisTest is super embedded throughout our testing. Things like get_data_path(), assertCML() and assertArrayEqual() are everywhere. Rewriting the tests to a point where an auto-converter can handle them would likely take a similar amount of time to just converting to PyTest ourselves.
Bonus points: if we manage to agree on some common conventions (e.g. how we use fixtures, conftest.py etcetera) BEFORE converting anything, then a tracker such as the above could also double up as a tracker of where we have rolled out these conventions (with a 5% error for the PyTest usages we have already written!)
Translation Guide
Some methods inherited from unittest will need replacing with pytest friendly equivalents. For developer convenience while translating, here is a table of unittest methods and their replacement code. Feel free to add to or edit this table as appropriate.
unittest method |
pytest equivalent |
|---|---|
assertTrue(x) |
assert x |
assertFalse(x) |
assert not x |
assertRegex(x, y) |
assert re.match(y, x) |
assertRaisesRegex(cls, msg_re) |
with pytest.raises(cls, match=msg_re) |
Random Notes
- best not to use
@staticmethodon a fixture- this it's OK when it passes,
- but a test-fail gives bad result like :"
E AttributeError: 'staticmethod' object has no attribute '__name__'"