Repository: geopandas/geopandas
Pull request #3126 (2024-01-05 09:14:53)

MAINT: reduce warnings in the tests
Follow up on https://github.com/geopandas/geopandas/pull/2966


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1ac362f..1f88c9fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@ Notes on dependencies:
   currently supported is shapely >= 2. As a consequence, spatial indexing based on the
   rtree package has also been removed. (#3035)
 
+API changes:
+
+- `unary_union` is now deprecated and replaced by the `union_all` method (#3007).
+
 New methods:
 
 - Added `count_coordinates` method from shapely to GeoSeries/GeoDataframe (#3026).
@@ -43,6 +47,12 @@ Bug fixes:
 - Fix bug in `pandas.concat` CRS consistency checking where CRS differing by WKT
   whitespace only were treated as incompatible (#3023).
 
+Deprecations and compatibility notes:
+
+- The deprecation of `geopandas.datasets` has been enforced and the module has been 
+  removed. New sample datasets are now available in the 
+  [geodatasets](https://geodatasets.readthedocs.io/en/latest/) package (#3084). 
+
 ## Version 0.14.2 (Jan 4, 2024)
 
 - Fix regression in `overlay` where using `buffer(0)` instead of `make_valid` internally
@@ -83,6 +93,7 @@ New methods:
 New features and improvements:
 
 - Added ``exclusive`` parameter to ``sjoin_nearest`` method for Shapely >= 2.0 (#2877)
+- Added ``GeoDataFrame.active_geometry_name`` property returning the active geometry column's name or None if no active geometry column is set.
 - The ``to_file()`` method will now automatically detect the FlatGeoBuf driver
   for files with the `.fgb` extension (#2958)
 
diff --git a/benchmarks/clip.py b/benchmarks/clip.py
index 235d994f..8e3d9573 100644
--- a/benchmarks/clip.py
+++ b/benchmarks/clip.py
@@ -1,11 +1,21 @@
-from geopandas import read_file, datasets, clip
+from geopandas import read_file, clip
 from shapely.geometry import box
 
+try:
+    from geopandas.tests.util import _NATURALEARTH_LOWRES
+    from geopandas.tests.util import _NATURALEARTH_CITIES
+except:
+    # geopandas <=0.14 compat
+    from geopandas.datasets import get_path
+
+    _NATURALEARTH_LOWRES = get_path("naturalearth_lowres")
+    _NATURALEARTH_CITIES = get_path("naturalearth_cities")
+
 
 class Bench:
     def setup(self, *args):
-        world = read_file(datasets.get_path("naturalearth_lowres"))
-        capitals = read_file(datasets.get_path("naturalearth_cities"))
+        world = read_file(_NATURALEARTH_LOWRES)
+        capitals = read_file(_NATURALEARTH_CITIES)
         self.bounds = [box(*geom.bounds) for geom in world.geometry]
         self.points = capitals
 
diff --git a/benchmarks/geom_methods.py b/benchmarks/geom_methods.py
index 5af5d7c5..cccad59e 100644
--- a/benchmarks/geom_methods.py
+++ b/benchmarks/geom_methods.py
@@ -134,8 +134,8 @@ class Bench:
     def time_bounds(self, *args):
         self.triangles.bounds
 
-    def time_unary_union(self, *args):
-        self.triangles.unary_union
+    def time_union_all(self, *args):
+        self.triangles.union_all()
 
     def time_buffer(self, *args):
         self.points.buffer(2)
diff --git a/benchmarks/overlay.py b/benchmarks/overlay.py
index cd352e59..47778cb4 100644
--- a/benchmarks/overlay.py
+++ b/benchmarks/overlay.py
@@ -1,7 +1,8 @@
-from geopandas import GeoDataFrame, GeoSeries, read_file, datasets, overlay
+from geopandas import GeoDataFrame, GeoSeries, read_file, overlay
 import numpy as np
 from shapely.geometry import Point, Polygon
-
+from geopandas.tests.util import _NATURALEARTH_LOWRES
+from geopandas.tests.util import _NATURALEARTH_CITIES
 
 class Countries:
     param_names = ["how"]
@@ -10,8 +11,8 @@ class Countries:
     ]
 
     def setup(self, *args):
-        world = read_file(datasets.get_path("naturalearth_lowres"))
-        capitals = read_file(datasets.get_path("naturalearth_cities"))
+        world = read_file(_NATURALEARTH_LOWRES)
+        capitals = read_file(_NATURALEARTH_CITIES)
         countries = world[["geometry", "name"]]
         countries = countries.to_crs("+init=epsg:3395")[countries.name != "Antarctica"]
         capitals = capitals.to_crs("+init=epsg:3395")
diff --git a/benchmarks/sindex.py b/benchmarks/sindex.py
index bbd15a62..a812c02f 100644
--- a/benchmarks/sindex.py
+++ b/benchmarks/sindex.py
@@ -1,6 +1,7 @@
 from shapely.geometry import Point
-
-from geopandas import read_file, datasets, GeoSeries
+from geopandas.tests.util import _NATURALEARTH_LOWRES
+from geopandas.tests.util import _NATURALEARTH_CITIES
+from geopandas import read_file, GeoSeries
 
 
 # Derive list of valid query predicates based on underlying index backend;
@@ -12,8 +13,8 @@ geom_types = ("mixed", "points", "polygons")
 
 
 def generate_test_df():
-    world = read_file(datasets.get_path("naturalearth_lowres"))
-    capitals = read_file(datasets.get_path("naturalearth_cities"))
+    world = read_file(_NATURALEARTH_LOWRES)
+    capitals = read_file(_NATURALEARTH_CITIES)
     countries = world.to_crs("epsg:3395")[["geometry"]]
     capitals = capitals.to_crs("epsg:3395")[["geometry"]]
     mixed = capitals.append(countries)  # get a mix of geometries
diff --git a/benchmarks/transform.py b/benchmarks/transform.py
index 673d1786..789335fd 100644
--- a/benchmarks/transform.py
+++ b/benchmarks/transform.py
@@ -1,12 +1,12 @@
-from geopandas import GeoDataFrame, GeoSeries, read_file, datasets
+from geopandas import GeoDataFrame, GeoSeries, read_file
 import numpy as np
 import pandas as pd
 from shapely.geometry import Point
-
+from geopandas.tests.util import _NYBB
 
 class CRS:
     def setup(self):
-        nybb = read_file(datasets.get_path("nybb"))
+        nybb = read_file(_NYBB)
         self.long_nybb = GeoDataFrame(pd.concat(10 * [nybb]), crs=nybb.crs)
 
         num_points = 20000
diff --git a/doc/nyc_boros.py b/doc/nyc_boros.py
index c94d171c..3908d8d7 100644
--- a/doc/nyc_boros.py
+++ b/doc/nyc_boros.py
@@ -56,7 +56,7 @@ R = 2000  # radius of buffer in feet
 xc = (xmax - xmin) * np.random.random(N) + xmin
 yc = (ymax - ymin) * np.random.random(N) + ymin
 pts = GeoSeries([Point(x, y) for x, y in zip(xc, yc)])
-mp = pts.buffer(R).unary_union
+mp = pts.buffer(R).union_all()
 boros_with_holes = boros.geometry - mp
 boros_with_holes.plot()
 plt.xticks(rotation=90)
diff --git a/doc/source/docs/reference/geodataframe.rst b/doc/source/docs/reference/geodataframe.rst
index dc49c40d..d6a8090a 100644
--- a/doc/source/docs/reference/geodataframe.rst
+++ b/doc/source/docs/reference/geodataframe.rst
@@ -49,6 +49,7 @@ Active geometry handling
 
    GeoDataFrame.rename_geometry
    GeoDataFrame.set_geometry
+   GeoDataFrame.active_geometry_name
 
 Aggregating and exploding
 -------------------------
diff --git a/doc/source/docs/reference/geoseries.rst b/doc/source/docs/reference/geoseries.rst
index 5a3dbc30..d0f08e9f 100644
--- a/doc/source/docs/reference/geoseries.rst
+++ b/doc/source/docs/reference/geoseries.rst
@@ -142,7 +142,7 @@ Aggregating and exploding
 .. autosummary::
    :toctree: api/
 
-   GeoSeries.unary_union
+   GeoSeries.union_all
    GeoSeries.explode
 
 Serialization / IO / conversion
diff --git a/doc/source/docs/user_guide/aggregation_with_dissolve.rst b/doc/source/docs/user_guide/aggregation_with_dissolve.rst
index e6870168..8520831f 100644
--- a/doc/source/docs/user_guide/aggregation_with_dissolve.rst
+++ b/doc/source/docs/user_guide/aggregation_with_dissolve.rst
@@ -16,7 +16,7 @@ In a non-spatial setting, when you need summary statistics of the data, you can
 
 :meth:`~geopandas.GeoDataFrame.dissolve` can be thought of as doing three things:
 
-(a) it dissolves all the geometries within a given group together into a single geometric feature (using the :attr:`~geopandas.GeoSeries.unary_union` method), and
+(a) it dissolves all the geometries within a given group together into a single geometric feature (using the :meth:`~geopandas.GeoSeries.union_all` method), and
 (b) it aggregates all the rows of data in a group using :ref:`groupby.aggregate <groupby.aggregate>`, and
 (c) it combines those two results.
 
diff --git a/doc/source/docs/user_guide/geometric_manipulations.rst b/doc/source/docs/user_guide/geometric_manipulations.rst
index 0d5985e5..ac74c5a6 100644
--- a/doc/source/docs/user_guide/geometric_manipulations.rst
+++ b/doc/source/docs/user_guide/geometric_manipulations.rst
@@ -54,7 +54,7 @@ Constructive methods
 
   Returns a :class:`~geopandas.GeoSeries` of geometries containing all distinct
   vertices of each input geometry as a multipoint.
-  
+
 .. method:: GeoSeries.offset_curve(distance, quad_segs=8, join_style="round", mitre_limit=5.0)
 
   Returns a :class:`~geopandas.GeoSeries` containing a `Linestring` or `MultiLineString`
@@ -75,7 +75,7 @@ Constructive methods
   Returns a :class:`~geopandas.GeoSeries` with additional vertices added to line
   segments based on max_segment_length.
 
-.. attribute:: GeoSeries.unary_union
+.. method:: GeoSeries.union_all()
 
   Return a geometry containing the union of all geometries in the :class:`~geopandas.GeoSeries`.
 
@@ -217,7 +217,7 @@ geometry with
 
 .. sourcecode:: python
 
-    >>> mp = circles.unary_union
+    >>> mp = circles.union_all()
 
 To extract the part of this geometry contained in each borough, you can
 just use:
diff --git a/doc/source/docs/user_guide/missing_empty.rst b/doc/source/docs/user_guide/missing_empty.rst
index 92cf29c8..e4230430 100644
--- a/doc/source/docs/user_guide/missing_empty.rst
+++ b/doc/source/docs/user_guide/missing_empty.rst
@@ -22,7 +22,7 @@ empty geometries:
   a Shapely geometry object.
 - **Missing geometries** are unknown values in a GeoSeries. They will typically
   be propagated in operations (for example in calculations of the area or of
-  the intersection), or ignored in reductions such as :attr:`~GeoSeries.unary_union`.
+  the intersection), or ignored in reductions such as :meth:`~GeoSeries.union_all`.
   The scalar object (when accessing a single element of a GeoSeries) is the
   Python ``None`` object.
 
diff --git a/geopandas/array.py b/geopandas/array.py
index 4b4abb95..ef726feb 100644
--- a/geopandas/array.py
+++ b/geopandas/array.py
@@ -811,20 +811,16 @@ class GeometryArray(ExtensionArray):
     #
 
     def unary_union(self):
-        warning_msg = (
-            "`unary_union` returned None due to all-None GeoSeries. In future, "
-            "`unary_union` will return 'GEOMETRYCOLLECTION EMPTY' instead."
+        warnings.warn(
+            "The 'unary_union' attribute is deprecated, "
+            "use the 'union_all' method instead.",
+            FutureWarning,
+            stacklevel=2,
         )
-        data = shapely.union_all(self._data)
-        if data is None or data.is_empty:
-            warnings.warn(
-                warning_msg,
-                FutureWarning,
-                stacklevel=4,
-            )
-            return None
-        else:
-            return data
+        return self.union_all()
+
+    def union_all(self):
+        return shapely.union_all(self._data)
 
     #
     # Affinity operations
diff --git a/geopandas/base.py b/geopandas/base.py
index c641cfa7..053fda62 100644
--- a/geopandas/base.py
+++ b/geopandas/base.py
@@ -1472,17 +1472,42 @@ GeometryCollection
     #
 
     @property
-    def cascaded_union(self):
-        """Deprecated: use `unary_union` instead"""
+    def unary_union(self):
+        """Returns a geometry containing the union of all geometries in the
+        ``GeoSeries``.
+
+        The ``unary_union`` attribute is deprecated. Use :meth:`union_all`
+        instead.
+
+        Examples
+        --------
+
+        >>> from shapely.geometry import box
+        >>> s = geopandas.GeoSeries([box(0,0,1,1), box(0,0,2,2)])
+        >>> s
+        0    POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))
+        1    POLYGON ((2 0, 2 2, 0 2, 0 0, 2 0))
+        dtype: geometry
+
+        >>> union = s.unary_union
+        >>> print(union)
+        POLYGON ((0 1, 0 2, 2 2, 2 0, 1 0, 0 0, 0 1))
+
+        See also
+        --------
+        GeoSeries.union_all
+        """
+
         warn(
-            "The 'cascaded_union' attribute is deprecated, use 'unary_union' instead",
+            "The 'unary_union' attribute is deprecated, "
+            "use the 'union_all()' method instead.",
             FutureWarning,
             stacklevel=2,
         )
-        return self.geometry.values.unary_union()
 
-    @property
-    def unary_union(self):
+        return self.geometry.values.union_all()
+
+    def union_all(self):
         """Returns a geometry containing the union of all geometries in the
         ``GeoSeries``.
 
@@ -1496,11 +1521,11 @@ GeometryCollection
         1    POLYGON ((2 0, 2 2, 0 2, 0 0, 2 0))
         dtype: geometry
 
-        >>> union = s.unary_union
+        >>> union = s.union_all()
         >>> print(union)
         POLYGON ((0 1, 0 2, 2 2, 2 0, 1 0, 0 0, 0 1))
         """
-        return self.geometry.values.unary_union()
+        return self.geometry.values.union_all()
 
     #
     # Binary operations that return a pandas Series
@@ -4971,7 +4996,7 @@ GeometryCollection
             result = self.geometry.apply(
                 lambda x: points_from_xy(
                     *sample_function(x, size=size, **kwargs).T
-                ).unary_union()
+                ).union_all()
                 if not (x.is_empty or x is None or "Polygon" not in x.geom_type)
                 else MultiPoint(),
             )
diff --git a/geopandas/datasets/__init__.py b/geopandas/datasets/__init__.py
index bed996ad..c0c03050 100644
--- a/geopandas/datasets/__init__.py
+++ b/geopandas/datasets/__init__.py
@@ -1,59 +1,25 @@
-import os
-
-from warnings import warn
-
-__all__ = ["available", "get_path"]
-
-_module_path = os.path.dirname(__file__)
-_available_dir = [p for p in next(os.walk(_module_path))[1] if not p.startswith("__")]
-_available_zip = {"nybb": "nybb_16a.zip"}
-available = _available_dir + list(_available_zip.keys())
+__all__ = []
+available = []  # previously part of __all__
+_prev_available = ["naturalearth_cities", "naturalearth_lowres", "nybb"]
 
 
 def get_path(dataset):
-    """
-    Get the path to the data file.
-
-    Parameters
-    ----------
-    dataset : str
-        The name of the dataset. See ``geopandas.datasets.available`` for
-        all options.
-
-    Examples
-    --------
-    >>> geopandas.datasets.get_path("naturalearth_lowres")  # doctest: +SKIP
-    '.../python3.8/site-packages/geopandas/datasets/\
-naturalearth_lowres/naturalearth_lowres.shp'
-
-    """
     ne_message = "https://www.naturalearthdata.com/downloads/110m-cultural-vectors/."
     nybb_message = (
         "the geodatasets package.\n\nfrom geodatasets import get_path\n"
         "path_to_file = get_path('nybb')\n"
     )
-    depr_warning = (
-        "The geopandas.dataset module is deprecated and will be removed in GeoPandas "
+    error_msg = (
+        "The geopandas.dataset has been deprecated and was removed in GeoPandas "
         f"1.0. You can get the original '{dataset}' data from "
         f"{ne_message if 'natural' in dataset else nybb_message}"
     )
-
-    if dataset in _available_dir:
-        warn(
-            depr_warning,
-            FutureWarning,
-            stacklevel=2,
-        )
-        return os.path.abspath(os.path.join(_module_path, dataset, dataset + ".shp"))
-    elif dataset in _available_zip:
-        warn(
-            depr_warning,
-            FutureWarning,
-            stacklevel=2,
-        )
-        fpath = os.path.abspath(os.path.join(_module_path, _available_zip[dataset]))
-        return "zip://" + fpath
+    if dataset in _prev_available:
+        raise AttributeError(error_msg)
     else:
-        msg = "The dataset '{data}' is not available. ".format(data=dataset)
-        msg += "Available datasets are {}".format(", ".join(available))
-        raise ValueError(msg)
+        error_msg = (
+            "The geopandas.dataset has been deprecated and "
+            "was removed in GeoPandas 1.0. New sample datasets are now available "
+            "in the geodatasets package (https://geodatasets.readthedocs.io/en/latest/)"
+        )
+        raise AttributeError(error_msg)
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.README.html b/geopandas/datasets/naturalearth_cities/naturalearth_cities.README.html
deleted file mode 100644
index 2f5786f0..00000000
--- a/geopandas/datasets/naturalearth_cities/naturalearth_cities.README.html
+++ /dev/null
@@ -1,336 +0,0 @@
-
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
-
-<head profile="http://gmpg.org/xfn/11">
-<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-
-<title>Populated Places | Natural Earth</title>
-
-<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
-<link rel="alternate" type="application/rss+xml" title="Natural Earth RSS Feed" href="http://www.naturalearthdata.com/feed/" />
-<link rel="pingback" href="http://www.naturalearthdata.com/xmlrpc.php" />
-<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/themes/NEV/includes/js/suckerfish.js"></script>
-<!--[if lt IE 7]>
-    <script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE7.js" type="text/javascript"></script>
-    <script defer="defer" type="text/javascript" src="http://www.naturalearthdata.com/wp-content/themes/NEV/includes/js/pngfix.js"></script>
-<![endif]--> 
-<link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/themes/NEV/style.css" type="text/css" media="screen" />
-
-<meta name='Admin Management Xtended WordPress plugin' content='2.1.1' />
-<link rel="alternate" type="application/rss+xml" title="Natural Earth &raquo; Populated Places Comments Feed" href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-populated-places/feed/" />
-<link rel='stylesheet' id='sociable-front-css-css'  href='http://www.naturalearthdata.com/wp-content/plugins/sociable/sociable.css?ver=2.9.2' type='text/css' media='' />
-<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://www.naturalearthdata.com/xmlrpc.php?rsd" />
-<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://www.naturalearthdata.com/wp-includes/wlwmanifest.xml" /> 
-<link rel='index' title='Natural Earth' href='http://www.naturalearthdata.com' />
-<link rel='start' title='Welcome to the Natural Earth Blog' href='http://www.naturalearthdata.com/blog/miscellaneous/test/' />
-<link rel='prev' title='Antarctic Ice Shelves' href='http://www.naturalearthdata.com/downloads/10m-physical-vectors/10m-antarctic-ice-shelves/' />
-<link rel='next' title='Admin 1 &#8211; States, Provinces' href='http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-admin-1-states-provinces/' />
-<meta name="generator" content="WordPress 2.9.2" />
-
-<!-- All in One SEO Pack 1.6.10.2 by Michael Torbert of Semper Fi Web Design[309,448] -->
-<meta name="description" content="City and town points, from Tokyo to Wasilla, Cairo to Kandahar About Point symbols with name attributes. Includes all admin-0 and many" />
-<link rel="canonical" href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-populated-places/" />
-<!-- /all in one seo pack -->
-
-	<!-- begin gallery scripts -->
-    <link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/css/jd.gallery.css.php" type="text/css" media="screen" charset="utf-8"/>
-	<link rel="stylesheet" href="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/css/jd.gallery.css" type="text/css" media="screen" charset="utf-8"/>
-	<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/mootools.v1.11.js"></script>
-	<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/jd.gallery.js.php"></script>
-	<script type="text/javascript" src="http://www.naturalearthdata.com/wp-content/plugins/featured-content-gallery/scripts/jd.gallery.transitions.js"></script>
-	<!-- end gallery scripts -->
-<style type="text/css">.broken_link, a.broken_link {
-	text-decoration: line-through;
-}</style><link href="http://www.naturalearthdata.com/wp-content/themes/NEV/css/default.css" rel="stylesheet" type="text/css" />
-	<style type="text/css">.recentcomments a{display:inline !important;padding:0 !important;margin:0 !important;}</style>
-<!--[if lte IE 7]>
-<link rel="stylesheet" type="text/css" href="http://www.naturalearthdata.com/wp-content/themes/NEV/ie.css" />
-<![endif]-->
-<script src="http://www.naturalearthdata.com/wp-content/themes/NEV/js/jquery-1.2.6.min.js" type="text/javascript" charset="utf-8"></script>
-<script>
-     jQuery.noConflict();
-</script>
-<script type="text/javascript" charset="utf-8">
-	$(function(){
-		var tabContainers = $('div#maintabdiv > div');
-		tabContainers.hide().filter('#comments').show();
-		
-		$('div#maintabdiv ul#tabnav a').click(function () {
-				tabContainers.hide();
-				tabContainers.filter(this.hash).show();
-				$('div#maintabdiv ul#tabnav a').removeClass('current');
-				$(this).addClass('current');
-				return false;
-			}).filter('#comments').click();
-		
-		
-	});
-</script>
-
-		<script type="text/javascript" language="javascript" src="http://www.naturalearthdata.com/dataTables/media/js/jquery.dataTables.js"></script>
-		<script type="text/javascript" charset="utf-8">
-			$(document).ready(function() {
-				$('#ne_table').dataTable();
-			} );
-		</script>
-
-</head>
-<body>
-<div id="page">
-<div id="header">
-	<div id="headerimg">		
-        <h1><a href="http://www.naturalearthdata.com/"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/nev_logo.png" alt="Natural Earth title="Natural Earth" /></a></h1> 
-        <div class="description">Free vector and raster map data at 1:10m, 1:50m, and 1:110m scales</div> 
-        <div class="header_search"><form method="get" id="searchform" action="http://www.naturalearthdata.com/">
-<label class="hidden" for="s">Search for:</label>
-<div><input type="text" value="" name="s" id="s" />
-<input type="submit" id="searchsubmit" value="Search" />
-</div>
-</form>
-</div>
-<!--<div class="translate_panel" style="align:top; margin-left:650px; top:50px;">
-<div id="google_translate_element" style="float:left;"></div>
-<script>
-function googleTranslateElementInit() {
- new google.translate.TranslateElement({
-   pageLanguage: 'en'
- }, 'google_translate_element');
-}
-</script>
-<script src="http://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script>
-</div>-->
-	</div>
-    
-</div>
-
-<div id="pagemenu" style="align:bottom;">
-    <ul id="page-list" class="clearfix"><li class="page_item page-item-4"><a href="http://www.naturalearthdata.com" title="Home">Home</a></li>
-<li class="page_item page-item-10"><a href="http://www.naturalearthdata.com/features/" title="Features">Features</a></li>
-<li class="page_item page-item-12"><a href="http://www.naturalearthdata.com/downloads/" title="Downloads">Downloads</a></li>
-<li class="page_item page-item-6 current_page_parent"><a href="http://www.naturalearthdata.com/blog/" title="Blog">Blog</a></li>
-<li class="page_item page-item-14"><a href="http://www.naturalearthdata.com/forums" title="Forums">Forums</a></li>
-<li class="page_item page-item-366"><a href="http://www.naturalearthdata.com/corrections" title="Corrections">Corrections</a></li>
-<li class="page_item page-item-16"><a href="http://www.naturalearthdata.com/about/" title="About">About</a></li>
-</ul>    
-</div>
-
-<hr />	<div id="main">
-	<div id="content" class="narrowcolumn">
-
-				
-									&laquo; <a href="http://www.naturalearthdata.com/downloads/10m-cultural-vectors/">1:10m Cultural Vectors</a>&nbsp;
-						   <div class="post" id="post-472">
-       		<h2>Populated Places</h2>
-			<div class="entry">
-				<div class="downloadPromoBlock" style="float: left;">
-<div style="float: left; width: 170px;"><img class="alignnone size-full wp-image-1918" title="pop_thumb" src="http://www.naturalearthdata.com/wp-content/uploads/2009/09/pop_thumb.png" alt="pop_thumb" width="150" height="97" /></div>
-<div style="float: left; width: 410px;"><em>City and town points, from Tokyo to Wasilla, Cairo to Kandahar</em>
-<div class="download-link-div">
-	<a class="download-link" rel="nofollow" title="Downloaded 26754 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places.zip');">Download populated places</a> <span class="download-link-span">(1.51 MB) version 2.0.0</span> 
-</div> <div class="download-link-div">
-	<a class="download-link" rel="nofollow" title="Downloaded 2515 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places_simple.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places_simple.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places_simple.zip');">Download simple (less columns)</a> <span class="download-link-span">(719.87 KB) version 2.0.0</span> 
-</div>
-<span id="more-472"></span></div>
-</div>
-<div class="downloadMainBlock" style="float: left;">
-<p><strong>About</strong></p>
-<p>Point symbols with name attributes. Includes all admin-0 and many admin-1 capitals, major cities and towns, plus a sampling of smaller towns in sparsely inhabited regions. We favor regional significance over population census in determining our selection of places. Use the scale rankings to filter the number of towns that appear on your map.</p>
-<p><img class="alignnone size-full wp-image-1920" title="pop_banner" src="http://www.naturalearthdata.com/wp-content/uploads/2009/09/pop_banner.png" alt="pop_banner" width="580" height="150" /></p>
-<p><a href="http://www.ornl.gov/sci/landscan/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.ornl.gov/sci/landscan/');">LandScan</a> derived population estimates are provided for 90% of our cities. Those lacking population estimates are often in sparsely inhabited areas. We provide a range of population values that account for the total &#8220;metropolitan&#8221; population rather than it&#8217;s administrative boundary population. Use the PopMax column to size your town labels. Starting in version 1.1, popMax has been throttled down to the UN estimated metro population for the ~500 largest urban areas in the world. This affects towns in China, India, and parts of Africa where our Landscan counting method usually over estimated.</p>
-<p>Population estimates were derived from the LANDSCAN dataset maintained and distributed by the Oak Ridge National Laboratory. These data were converted from raster to vector and pixels with fewer than 200 persons per square kilometer were removed from the dataset as they were classified as rural. Once urban pixels were selected, these pixels were aggregated into contiguous units. Concurrently Thiessen polygons were created based on the selected city points. The Thiessen polygons were used to intersect the contiguous city boundaries to produce bounded areas for the cities. As a result, our estimates capture a metropolitan and micropolitan populations per city regardless of administrative units.</p>
-<p>Once intersected, the contiguous polygons were recalculated, using aerial interpolation assuming uniform population distribution within each pixel, to determine the population total. This process was conducted multiple times, for each scale level, to produce population estimates for each city at nested scales of 1:300 million, 1:110 million, 1:50 million, 1:20 million, and 1:10 million. </p>
-<div class="download-link-div">
-	<a class="download-link" rel="nofollow" title="Downloaded 481 times (Shapefile, geoDB, or TIFF format)" onclick="if (window.urchinTracker) urchinTracker ('http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_urban_areas_landscan.zip');" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_urban_areas_landscan.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_urban_areas_landscan.zip');">Download landscan urban areas</a> <span class="download-link-span">(13.01 MB) version 2.0.0</span> 
-</div>
-<p><strong>Population ranks</strong></p>
-<p>Are calculated as rank_max and rank_min using this general VB formula that can be pasted into ArcMap Field Calculator advanced area (set your output to x):</p>
-<blockquote><p>
-a = [pop_max]</p>
-<p>if( a > 10000000 ) then
-x = 14
-elseif( a > 5000000 ) then
-x = 13
-elseif( a > 1000000 ) then
-x = 12
-elseif( a > 500000 ) then
-x = 11
-elseif( a > 200000 ) then
-x = 10
-elseif( a > 100000 ) then
-x = 9
-elseif( a > 50000 ) then
-x = 8
-elseif( a > 20000 ) then
-x = 7
-elseif( a > 10000 ) then
-x = 6
-elseif( a > 5000 ) then
-x = 5
-elseif( a > 2000 ) then
-x = 4
-elseif( a > 1000 ) then
-x = 3
-elseif( a > 200 ) then
-x = 2
-elseif( a > 0 ) then
-x = 1
-else
-x = 0
-end if</p></blockquote>
-<p><strong>Issues</strong></p>
-<p>While we don&#8217;t want to show every admin-1 capital, for those countries where we show most admin-1 capitals, we should have a complete set. If you find we are missing one, please log it in the Cx tool at right.</p>
-<p><strong>Version History</strong></p>
-	<ul>
-					<li>
-									<a rel="nofollow" title="Download version 2.0.0 of ne_10m_populated_places.zip" href="http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip" onclick="javascript:pageTracker._trackPageview('/downloads/http///download/10m/cultural/ne_10m_populated_places.zip');">2.0.0</a>								
-							</li>
-					<li>
-									1.4.0								
-							</li>
-					<li>
-									1.3.0								
-							</li>
-					<li>
-									1.1.0								
-							</li>
-					<li>
-									0.9.0								
-							</li>
-			</ul>
-
-<p><a href="https://github.com/nvkelso/natural-earth-vector/blob/master/CHANGELOG" onclick="javascript:pageTracker._trackPageview('/outbound/article/https://github.com/nvkelso/natural-earth-vector/blob/master/CHANGELOG');">The master changelog is available on Github »</a>
-</div>
-
-<div class="sociable">
-<div class="sociable_tagline">
-<strong>Share and Enjoy:</strong>
-</div>
-<ul>
-	<li class="sociablefirst"><a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=Populated%20Places%20-%20http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://twitter.com/home?status=Populated%20Places%20-%20http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F');" title="Twitter"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Twitter" alt="Twitter" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-343px -55px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;t=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.facebook.com/share.php?u=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;t=Populated%20Places');" title="Facebook"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Facebook" alt="Facebook" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-343px -1px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;bodytext=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;bodytext=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="Digg"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Digg" alt="Digg" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-235px -1px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;notes=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://delicious.com/post?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;notes=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="del.icio.us"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="del.icio.us" alt="del.icio.us" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-199px -1px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;annotation=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;annotation=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="Google Bookmarks"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Google Bookmarks" alt="Google Bookmarks" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-91px -19px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://slashdot.org/bookmark.pl?title=Populated%20Places&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://slashdot.org/bookmark.pl?title=Populated%20Places&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F');" title="Slashdot"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Slashdot" alt="Slashdot" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-145px -55px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.stumbleupon.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places');" title="StumbleUpon"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="StumbleUpon" alt="StumbleUpon" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-217px -55px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="mailto:?subject=Populated%20Places&amp;body=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F" title="email"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif"  title="email" alt="email" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-325px -1px" class="sociable-hovers" /></a></li>
-	<li><a rel="nofollow"  target="_blank" href="http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;source=Natural+Earth+Free+vector+and+raster+map+data+at+1%3A10m%2C+1%3A50m%2C+and+1%3A110m+scales&amp;summary=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.linkedin.com/shareArticle?mini=true&amp;url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places&amp;source=Natural+Earth+Free+vector+and+raster+map+data+at+1%3A10m%2C+1%3A50m%2C+and+1%3A110m+scales&amp;summary=%0D%0A%0D%0ACity%20and%20town%20points%2C%20from%20Tokyo%20to%20Wasilla%2C%20Cairo%20to%20Kandahar%0D%0A%5Bdrain%20file%2039%20show%20nev_download%5D%20%5Bdrain%20file%20224%20show%20nev_download%5D%0D%0A%0D%0A%0D%0A%0D%0A%0D%0AAbout%0D%0A%0D%0APoint%20symbols%20with%20name%20attributes.%20Includes%20all%20admin-0%20and%20many%20admin-1%20capitals%2C%20major%20citie');" title="LinkedIn"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="LinkedIn" alt="LinkedIn" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-1px -37px" class="sociable-hovers" /></a></li>
-	<li class="sociablelast"><a rel="nofollow"  target="_blank" href="http://reddit.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://reddit.com/submit?url=http%3A%2F%2Fwww.naturalearthdata.com%2Fdownloads%2F10m-cultural-vectors%2F10m-populated-places%2F&amp;title=Populated%20Places');" title="Reddit"><img src="http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.gif" title="Reddit" alt="Reddit" style="width: 16px; height: 16px; background: transparent url(http://www.naturalearthdata.com/wp-content/plugins/sociable/images/services-sprite.png) no-repeat; background-position:-55px -55px" class="sociable-hovers" /></a></li>
-</ul>
-</div>
-
-				
-			</div>
-
-		</div>
-		
-
-		</div>
-
-
-	<div id="sidebar">
-    	<ul><li id='text-5' class='widget widget_text'><h2 class="widgettitle">Stay up to Date</h2>
-			<div class="textwidget"> Know when a new version of Natural Earth is released by subscribing to our <a href="http://www.naturalearthdata.com/updates/" class="up-to-date-link" >announcement list</a>.</div>
-		</li></ul><ul><li id='text-2' class='widget widget_text'><h2 class="widgettitle">Find a Problem?</h2>
-			<div class="textwidget"><div>
-<div style="float:left; width:65px;"><a href="/corrections/index.php?a=add"><img class="alignleft" title="New Ticket" src="http://www.naturalearthdata.com/corrections/img/newticket.png" alt="" width="60" height="60" /></a></div><div class="textwidget" style="float:left;width:120px; font-size:1.2em; font-size-adjust:none; font-style:normal;
-font-variant:normal; font-weight:normal; line-height:normal;">Submit suggestions and bug reports via our <a href="/corrections/index.php?a=add">correction system</a> and track the progress of your edits.</div>
-</div></div>
-		</li></ul><ul><li id='text-3' class='widget widget_text'><h2 class="widgettitle">Join Our Community</h2>
-			<div class="textwidget"><div>
-<div style="float:left; width:65px;"><a href="/forums/"><img src="http://www.naturalearthdata.com/wp-content/uploads/2009/08/green_globe_chat_bubble_562e.png" alt="forums" title="Chat in the forum!" width="50" height="50" /></a></div><div class="textwidget" style="float:left;width:120px; font-size:1.2em; font-size-adjust:none; font-style:normal;
-font-variant:normal; font-weight:normal; line-height:normal;">Talk back and discuss Natural Earth in the <a href="/forums/">Forums</a>.</div>
-</div></div>
-		</li></ul><ul><li id='text-4' class='widget widget_text'><h2 class="widgettitle">Thank You</h2>
-			<div class="textwidget">Our data downloads are generously hosted by Florida State University.</div>
-		</li></ul>	</div>
-
-</div>
-
-<hr />
-<div id="footer">
-<div id="footerarea">
-	<div id="footerlogos">
-    	<p>Supported by:</p>
-        <div class="footer-ad-box">
-        	<a href="http://www.nacis.org" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/nacis.png" alt="NACIS" /></a>
-        </div>
-    	<div class="footer-ad-box">
-        	<a href="http://www.cartotalk.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/cartotalk_ad.png" alt="Cartotalk" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.mapgiving.org" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/mapgiving.png" alt="Mapgiving" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.geography.wisc.edu/cartography/" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/wisconsin.png" alt="University of Wisconsin Madison - Cartography Dept." /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.shadedrelief.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/shaded_relief.png" alt="Shaded Relief" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.xnrproductions.com " target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/xnr.png" alt="XNR Productions" /></a>
-        </div>
-        
-        <p style="clear:both;"></p>
-        
-       <div class="footer-ad-box">
-        	<a href="http://www.freac.fsu.edu" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/fsu.png" alt="Florida State University - FREAC" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.springercartographics.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/scllc.png" alt="Springer Cartographics LLC" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.washingtonpost.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/wpost.png" alt="Washington Post" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.redgeographics.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/redgeo.png" alt="Red Geographics" /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://kelsocartography.com/blog " target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/kelso.png" alt="Kelso Cartography" /></a>
-        </div>
-        
-        <p style="clear:both;"></p>
-        <div class="footer-ad-box">
-        	<a href="http://www.avenza.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/avenza.png" alt="Avenza Systems Inc." /></a>
-        </div>
-        <div class="footer-ad-box">
-        	<a href="http://www.stamen.com" target="_blank"><img src="http://www.naturalearthdata.com/wp-content/themes/NEV/images/stamen_ne_logo.png" alt="Stamen Design" /></a>
-        </div>
-
-
-    </div>
-    <p style="clear:both;"></p>
-	<span id="footerleft">
-		&copy; 2012. Natural Earth. All rights reserved.
-	</span>
-    <span id="footerright"> 
-    	<!-- Please help promote WordPress and simpleX. Do not remove -->   
-		<div>Powered by <a href="http://wordpress.org/">WordPress</a></div>
-        <div><a href="http://www.naturalearthdata.com/wp-admin">Staff Login &raquo;</a></div>
-    </span>
-</div>
-</div>
-		
-<!-- Google Analytics for WordPress | http://yoast.com/wordpress/google-analytics/ -->
-<script type="text/javascript">
-	var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-	document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
-	try {
-		var pageTracker = _gat._getTracker("UA-10168306-1");
-	} catch(err) {}
-</script>
-<script src="http://www.naturalearthdata.com/wp-content/plugins/google-analytics-for-wordpress/custom_se.js" type="text/javascript"></script>
-<script type="text/javascript">
-	try {
-		// Cookied already: 
-		pageTracker._trackPageview();
-	} catch(err) {}
-</script>
-<!-- End of Google Analytics code -->
-
-</body>
-</html>
\ No newline at end of file
diff --git a/geopandas/datasets/naturalearth_creation.py b/geopandas/datasets/naturalearth_creation.py
deleted file mode 100644
index 2942deb2..00000000
--- a/geopandas/datasets/naturalearth_creation.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
-Script that generates the included dataset 'naturalearth_lowres.shp'
-and 'naturalearth_cities.shp'.
-
-Raw data: https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/110m/cultural/ne_110m_admin_0_countries.zip
-Current version used: see code
-"""
-
-import geopandas as gpd
-import requests
-from pathlib import Path
-from zipfile import ZipFile
-import tempfile
-from shapely.geometry import box
-
-version = "latest"
-urlbase = "https://www.naturalearthdata.com/"
-urlbase += "http//www.naturalearthdata.com/download/110m/cultural/"
-
-
-def countries_override(world_raw):
-    # not ideal - fix some country codes
-    mask = world_raw["ISO_A3"].eq("-99") & world_raw["TYPE"].isin(
-        ["Sovereign country", "Country"]
-    )
-    world_raw.loc[mask, "ISO_A3"] = world_raw.loc[mask, "ADM0_A3"]
-    # backwards compatibility
-    return world_raw.rename(columns={"GDP_MD": "GDP_MD_EST"})
-
-
-# any change between versions?
-def df_same(new, old, dataset, log):
-    assert (new.columns == old.columns).all(), "columns should be the same"
-    if new.shape != old.shape:
-        dfc = old.merge(new, on="name", how="outer", suffixes=("_old", "_new")).loc[
-            lambda d: d.isna().any(axis=1)
-        ]
-        log.append(f"### {dataset} row count changed ###\n{dfc.to_markdown()}")
-        return False
-    dfc = new.compare(old)
-    if len(dfc) > 0:
-        log.append(f"### {dataset} data changed ###\n{dfc.to_markdown()}")
-    return len(dfc) == 0
-
-
-config = [
-    {
-        "file": "ne_110m_populated_places.zip",
-        "cols": ["NAME", "geometry"],
-        "current": gpd.datasets.get_path("naturalearth_cities"),
-    },
-    {
-        "file": "ne_110m_admin_0_countries.zip",
-        "cols": ["POP_EST", "CONTINENT", "NAME", "ISO_A3", "GDP_MD_EST", "geometry"],
-        "override": countries_override,
-        "current": gpd.datasets.get_path("naturalearth_lowres"),
-    },
-]
-
-downloads = {}
-log = []
-for dl in config:
-    with tempfile.TemporaryDirectory() as tmpdirname:
-        url = urlbase + dl["file"]
-        r = requests.get(
-            url,
-            stream=True,
-            headers={"User-Agent": "XY"},
-            params=None if version == "latest" else {"version": version},
-        )
-        assert (
-            r.status_code == 200
-        ), f"version: {version} does not exist. status: {r.status_code}"
-
-        f = Path(tmpdirname).joinpath(dl["file"])
-        with open(f, "wb") as fd:
-            for chunk in r.iter_content(chunk_size=128):
-                fd.write(chunk)
-        # extract the natural earth version
-        z = ZipFile(f)
-        version_f = [i for i in z.infolist() if "VERSION" in i.filename]
-        assert len(version_f) == 1, "failed to find VERSION file"
-        with open(z.extract(version_f[0], Path(tmpdirname).joinpath("v.txt"))) as f_:
-            dl_version = f_.read().strip()
-
-        # extract geodataframe from zip
-        gdf = gpd.read_file(f)
-        # maintain structure that geopandas distributes
-        if "override" in dl.keys():
-            gdf = dl["override"](gdf)
-        gdf = gdf.loc[:, dl["cols"]]
-        gdf = gdf.rename(columns={c: c.lower() for c in gdf.columns})
-
-        # override Crimea #2382
-        if dl["file"] == "ne_110m_admin_0_countries.zip":
-            crimean_bbox = box(32.274, 44.139, 36.65, 46.704)
-            crimea_only = (
-                gdf.loc[gdf.name == "Russia", "geometry"]
-                .iloc[0]
-                .intersection(crimean_bbox)
-            )
-            complete_ukraine = (
-                gdf.loc[gdf.name == "Ukraine", "geometry"].iloc[0].union(crimea_only)
-            )
-            correct_russia = (
-                gdf.loc[gdf.name == "Russia", "geometry"]
-                .iloc[0]
-                .difference(crimean_bbox)
-            )
-            r_ix = gdf.loc[gdf.name == "Russia"].index[0]
-            gdf.at[r_ix, "geometry"] = correct_russia
-
-            u_ix = gdf.loc[gdf.name == "Ukraine"].index[0]
-            gdf.at[u_ix, "geometry"] = complete_ukraine
-
-        # get changes between current version and new version
-        if not df_same(gdf, gpd.read_file(dl["current"]), dl["file"], log):
-            downloads[dl["file"]] = gdf
-
-
-# create change log that can be pasted into PR
-with open(f"CHANGE_{dl_version}.md", "w") as f:
-    f.write("\n\n".join(log))
-
-# save downloaded geodataframe to appropriate place
-for k, gdf_ in downloads.items():
-    f = [Path(c["current"]) for c in config if c["file"] == k][0]
-    gdf_.to_file(driver="ESRI Shapefile", filename=Path(f.parent.name).joinpath(f.name))
diff --git a/geopandas/geodataframe.py b/geopandas/geodataframe.py
index 7025ad0d..751d4814 100644
--- a/geopandas/geodataframe.py
+++ b/geopandas/geodataframe.py
@@ -17,7 +17,6 @@ from geopandas.base import GeoPandasBase, is_geometry_type
 from geopandas.geoseries import GeoSeries
 import geopandas.io
 from geopandas.explore import _explore
-from . import _compat as compat
 from ._decorator import doc
 
 
@@ -320,8 +319,6 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
                 level = frame[col]
             except KeyError:
                 raise ValueError("Unknown column %s" % col)
-            except Exception:
-                raise
             if isinstance(level, DataFrame):
                 raise ValueError(
                     "GeoDataFrame does not support setting the geometry column where "
@@ -398,6 +395,26 @@ class GeoDataFrame(GeoPandasBase, DataFrame):
             self.rename(columns={geometry_col: col}, inplace=inplace)
             self.set_geometry(col, inplace=inplace)
 
+    @property
+    def active_geometry_name(self):
+        """Return the name of the active geometry column
+
+        Returns a string name if a GeoDataFrame has an active geometry column set.
+        Otherwise returns None. You can also access the active geometry column using the
+        ``.geometry`` property. You can set a GeoSeries to be an active geometry
+        using the :meth:`~GeoDataFrame.set_geometry` method.
+
+        Returns
+        -------
+        str
+            name of an active geometry column or None
+
+        See also
+        --------
+        GeoDataFrame.set_geometry : set the active geometry
+        """
+        return self._geometry_column_name
+
     @property
     def crs(self):
         """
@@ -1537,13 +1554,6 @@ individually so that features may have different properties
         result = super().apply(
             func, axis=axis, raw=raw, result_type=result_type, args=args, **kwargs
         )
-        # pandas <1.4 re-attach last geometry col if lost
-        if (
-            not compat.PANDAS_GE_14
-            and isinstance(result, GeoDataFrame)
-            and result._geometry_column_name is None
-        ):
-            result._geometry_column_name = self._geometry_column_name
         # Reconstruct gdf if it was lost by apply
         if (
             isinstance(result, DataFrame)
@@ -1654,7 +1664,7 @@ individually so that features may have different properties
     ):
         """
         Dissolve geometries within `groupby` into single observation.
-        This is accomplished by applying the `unary_union` method
+        This is accomplished by applying the `union_all` method
         to all geometries within a groupself.
 
         Observations associated with each `groupby` group will be aggregated
@@ -1776,7 +1786,7 @@ individually so that features may have different properties
 
         # Process spatial component
         def merge_geometries(block):
-            merged_geom = block.unary_union
+            merged_geom = block.union_all()
             return merged_geom
 
         g = self.groupby(group_keys=False, **groupby_kwargs)[self.geometry.name].agg(
diff --git a/geopandas/io/file.py b/geopandas/io/file.py
index 60bf95fb..98fe7f8a 100644
--- a/geopandas/io/file.py
+++ b/geopandas/io/file.py
@@ -18,6 +18,7 @@ from urllib.parse import urlparse as parse_url
 from urllib.parse import uses_netloc, uses_params, uses_relative
 import urllib.request
 
+from geopandas._compat import PANDAS_GE_20
 
 _VALID_URLS = set(uses_relative + uses_netloc + uses_params)
 _VALID_URLS.discard("")
@@ -359,7 +360,7 @@ def _read_file_fiona(
                 assert len(bbox) == 4
             # handle loading the mask
             elif isinstance(mask, (GeoDataFrame, GeoSeries)):
-                mask = mapping(mask.to_crs(crs).unary_union)
+                mask = mapping(mask.to_crs(crs).union_all())
             elif isinstance(mask, BaseGeometry):
                 mask = mapping(mask)
 
@@ -408,7 +409,10 @@ def _read_file_fiona(
                 # fiona only supports up to ms precision (any microseconds are
                 # floating point rounding error)
                 if not (as_dt.dtype == "object"):
-                    df[k] = as_dt.dt.round(freq="ms")
+                    if PANDAS_GE_20:
+                        df[k] = as_dt.dt.as_unit("ms")
+                    else:
+                        df[k] = as_dt.dt.round(freq="ms")
             return df
 
 
diff --git a/geopandas/io/sql.py b/geopandas/io/sql.py
index 09b43d81..b321bb86 100644
--- a/geopandas/io/sql.py
+++ b/geopandas/io/sql.py
@@ -78,10 +78,6 @@ def _df_to_geodf(df, geom_col="geom", crs=None):
         load_geom_bytes = shapely.wkb.loads
         """Load from Python 3 binary."""
 
-        def load_geom_buffer(x):
-            """Load from Python 2 binary."""
-            return shapely.wkb.loads(str(x))
-
         def load_geom_text(x):
             """Load from binary encoded as text."""
             return shapely.wkb.loads(str(x), hex=True)
diff --git a/geopandas/plotting.py b/geopandas/plotting.py
index e863c041..19b8a97d 100644
--- a/geopandas/plotting.py
+++ b/geopandas/plotting.py
@@ -76,17 +76,10 @@ def _expand_kwargs(kwargs, multiindex):
     it (in place) to the correct length/formats with help of 'multiindex', unless
     the value appears to already be a valid (single) value for the key.
     """
-    import matplotlib
     from matplotlib.colors import is_color_like
     from typing import Iterable
 
-    mpl = Version(matplotlib.__version__)
-    if mpl >= Version("3.4"):
-        # alpha is supported as array argument with matplotlib 3.4+
-        scalar_kwargs = ["marker", "path_effects"]
-    else:
-        scalar_kwargs = ["marker", "alpha", "path_effects"]
-
+    scalar_kwargs = ["marker", "path_effects"]
     for att, value in kwargs.items():
         if "color" in att:  # color(s), edgecolor(s), facecolor(s)
             if is_color_like(value):
@@ -491,7 +484,7 @@ def plot_series(
             ax, points, values_, color=color_, cmap=cmap, **style_kwds
         )
 
-    plt.draw()
+    ax.figure.canvas.draw_idle()
     return ax
 
 
@@ -964,7 +957,7 @@ def plot_dataframe(
             n_cmap.set_array(np.array([]))
             ax.get_figure().colorbar(n_cmap, **legend_kwds)
 
-    plt.draw()
+    ax.figure.canvas.draw_idle()
     return ax
 
 
diff --git a/geopandas/datasets/README.md b/geopandas/tests/data/README.md
similarity index 97%
rename from geopandas/datasets/README.md
rename to geopandas/tests/data/README.md
index 625dbfca..c2e736de 100644
--- a/geopandas/datasets/README.md
+++ b/geopandas/tests/data/README.md
@@ -1,4 +1,4 @@
-# Datasets included with geopandas
+# Datasets previously included with geopandas
 
 - `'nybb'`: Borough boundaries of New York City, data provided Department of City Planning (DCP), https://data.cityofnewyork.us/City-Government/Borough-Boundaries/tqmj-j8zm
 - `'naturalearth_cities'`: capital cities, based on http://www.naturalearthdata.com/downloads/10m-cultural-vectors/110m-populated-places/
diff --git a/geopandas/tools/_random.py b/geopandas/tools/_random.py
index 795667fa..0119e337 100644
--- a/geopandas/tools/_random.py
+++ b/geopandas/tools/_random.py
@@ -64,7 +64,7 @@ def _uniform_line(geom, size, generator):
     """
 
     fracs = generator.uniform(size=size)
-    return from_shapely(geom.interpolate(fracs, normalized=True)).unary_union()
+    return from_shapely(geom.interpolate(fracs, normalized=True)).union_all()
 
 
 def _uniform_polygon(geom, size, generator):
@@ -80,4 +80,4 @@ def _uniform_polygon(geom, size, generator):
         )
         valid_samples = batch[batch.sindex.query(geom, predicate="contains")]
         candidates.extend(valid_samples)
-    return GeoSeries(candidates[:size]).unary_union
+    return GeoSeries(candidates[:size]).union_all()
diff --git a/geopandas/tools/clip.py b/geopandas/tools/clip.py
index e41c49a6..a47d02f6 100644
--- a/geopandas/tools/clip.py
+++ b/geopandas/tools/clip.py
@@ -185,7 +185,7 @@ def clip(gdf, mask, keep_geom_type=False):
         return gdf.iloc[:0]
 
     if isinstance(mask, (GeoDataFrame, GeoSeries)):
-        combined_mask = mask.geometry.unary_union
+        combined_mask = mask.geometry.union_all()
     else:
         combined_mask = mask
 
diff --git a/geopandas/tools/overlay.py b/geopandas/tools/overlay.py
index 107ad268..ff27211b 100644
--- a/geopandas/tools/overlay.py
+++ b/geopandas/tools/overlay.py
@@ -365,7 +365,7 @@ def overlay(df1, df2, how="intersection", keep_geom_type=None, make_valid=True):
 
             # level_0 created with above reset_index operation
             # and represents the original geometry collections
-            # TODO avoiding dissolve to call unary_union in this case could further
+            # TODO avoiding dissolve to call union_all in this case could further
             # improve performance (we only need to collect geometries in their
             # respective Multi version)
             dissolved = exploded.dissolve(by="level_0")
diff --git a/pyproject.toml b/pyproject.toml
index bdac183e..1823f613 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -54,10 +54,7 @@ include = ["geopandas", "geopandas.*"]
 
 [tool.setuptools.package-data]
 geopandas = [
-    "datasets/nybb_16a.zip",
-    "datasets/naturalearth_cities/*",
-    "datasets/naturalearth_lowres/*",
-    "tests/data/*",
+    "tests/data/null_geom.geojson"
 ]
 
 [tool.pytest.ini_options]
@@ -195,7 +192,7 @@ ignore = [ # space before : (needed for how black formats slicing)
     # explicit-f-string-type-conversion
     "RUF010",
 ]
-exclude = ["doc/*", "benchmarks/*", "versioneer.py", "geopandas/_version.py"]
+extend-exclude = ["doc/*", "benchmarks/*", "versioneer.py", "geopandas/_version.py"]
 
 [tool.ruff.per-file-ignores]
 "geopandas/__init__.py" = ["F401"]


Test patch:
diff --git a/geopandas/conftest.py b/geopandas/conftest.py
index 601c92fc..72ce280c 100644
--- a/geopandas/conftest.py
+++ b/geopandas/conftest.py
@@ -1,7 +1,46 @@
+import os.path
+
 import pytest
 import geopandas
+from geopandas.tests.util import _NYBB, _NATURALEARTH_LOWRES, _NATURALEARTH_CITIES
 
 
 @pytest.fixture(autouse=True)
 def add_geopandas(doctest_namespace):
     doctest_namespace["geopandas"] = geopandas
+
+
+# Datasets used in our tests
+
+
+@pytest.fixture(scope="session")
+def naturalearth_lowres() -> str:
+    # skip if data missing, unless on github actions
+    if os.path.isfile(_NATURALEARTH_LOWRES) or os.getenv("GITHUB_ACTIONS"):
+        return _NATURALEARTH_LOWRES
+    else:
+        pytest.skip("Naturalearth lowres dataset not found")
+
+
+@pytest.fixture(scope="session")
+def naturalearth_cities() -> str:
+    # skip if data missing, unless on github actions
+    if os.path.isfile(_NATURALEARTH_CITIES) or os.getenv("GITHUB_ACTIONS"):
+        return _NATURALEARTH_CITIES
+    else:
+        pytest.skip("Naturalearth cities dataset not found")
+
+
+@pytest.fixture(scope="session")
+def nybb_filename() -> str:
+    # skip if data missing, unless on github actions
+    if os.path.isfile(_NYBB[len("zip://") :]) or os.getenv("GITHUB_ACTIONS"):
+        return _NYBB
+    else:
+        pytest.skip("NYBB dataset not found")
+
+
+@pytest.fixture(scope="class")
+def _setup_class_nybb_filename(nybb_filename, request):
+    """Attach nybb_filename class attribute for unittest style setup_method"""
+    request.cls.nybb_filename = nybb_filename
diff --git a/geopandas/io/tests/test_arrow.py b/geopandas/io/tests/test_arrow.py
index 28b4190c..75ab9ec4 100644
--- a/geopandas/io/tests/test_arrow.py
+++ b/geopandas/io/tests/test_arrow.py
@@ -17,7 +17,6 @@ from shapely.geometry import box, Point, MultiPolygon
 import geopandas
 from geopandas import GeoDataFrame, read_file, read_parquet, read_feather
 from geopandas.array import to_wkb
-from geopandas.datasets import get_path
 from geopandas.io.arrow import (
     SUPPORTED_VERSIONS,
     _create_metadata,
@@ -60,9 +59,8 @@ def file_format(request):
         return read_feather, GeoDataFrame.to_feather
 
 
-def test_create_metadata():
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+def test_create_metadata(naturalearth_lowres):
+    df = read_file(naturalearth_lowres)
     metadata = _create_metadata(df)
 
     assert isinstance(metadata, dict)
@@ -125,9 +123,8 @@ def test_decode_metadata():
     assert _decode_metadata(None) is None
 
 
-def test_validate_dataframe():
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+def test_validate_dataframe(naturalearth_lowres):
+    df = read_file(naturalearth_lowres)
 
     # valid: should not raise ValueError
     _validate_dataframe(df)
@@ -290,11 +287,11 @@ def test_pandas_parquet_roundtrip1(tmpdir):
 
 
 @pytest.mark.parametrize(
-    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb"]
+    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb_filename"]
 )
-def test_pandas_parquet_roundtrip2(test_dataset, tmpdir):
-    test_dataset = "naturalearth_lowres"
-    df = DataFrame(read_file(get_path(test_dataset)).drop(columns=["geometry"]))
+def test_pandas_parquet_roundtrip2(test_dataset, tmpdir, request):
+    path = request.getfixturevalue(test_dataset)
+    df = DataFrame(read_file(path).drop(columns=["geometry"]))
 
     filename = os.path.join(str(tmpdir), "test.pq")
     df.to_parquet(filename)
@@ -305,15 +302,16 @@ def test_pandas_parquet_roundtrip2(test_dataset, tmpdir):
 
 
 @pytest.mark.parametrize(
-    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb"]
+    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb_filename"]
 )
-def test_roundtrip(tmpdir, file_format, test_dataset):
+def test_roundtrip(tmpdir, file_format, test_dataset, request):
     """Writing to parquet should not raise errors, and should not alter original
     GeoDataFrame
     """
+    path = request.getfixturevalue(test_dataset)
     reader, writer = file_format
 
-    df = read_file(get_path(test_dataset))
+    df = read_file(path)
     orig = df.copy()
 
     filename = os.path.join(str(tmpdir), "test.pq")
@@ -332,14 +330,13 @@ def test_roundtrip(tmpdir, file_format, test_dataset):
     assert_geodataframe_equal(df, pq_df)
 
 
-def test_index(tmpdir, file_format):
+def test_index(tmpdir, file_format, naturalearth_lowres):
     """Setting index=`True` should preserve index in output, and
     setting index=`False` should drop index from output.
     """
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset)).set_index("iso_a3")
+    df = read_file(naturalearth_lowres).set_index("iso_a3")
 
     filename = os.path.join(str(tmpdir), "test_with_index.pq")
     writer(df, filename, index=True)
@@ -353,13 +350,12 @@ def test_index(tmpdir, file_format):
 
 
 @pytest.mark.parametrize("compression", ["snappy", "gzip", "brotli", None])
-def test_parquet_compression(compression, tmpdir):
+def test_parquet_compression(compression, tmpdir, naturalearth_lowres):
     """Using compression options should not raise errors, and should
     return identical GeoDataFrame.
     """
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     filename = os.path.join(str(tmpdir), "test.pq")
     df.to_parquet(filename, compression=compression)
@@ -374,13 +370,12 @@ def test_parquet_compression(compression, tmpdir):
     reason="Feather only supported for pyarrow >= 0.17",
 )
 @pytest.mark.parametrize("compression", ["uncompressed", "lz4", "zstd"])
-def test_feather_compression(compression, tmpdir):
+def test_feather_compression(compression, tmpdir, naturalearth_lowres):
     """Using compression options should not raise errors, and should
     return identical GeoDataFrame.
     """
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     filename = os.path.join(str(tmpdir), "test.feather")
     df.to_feather(filename, compression=compression)
@@ -390,14 +385,13 @@ def test_feather_compression(compression, tmpdir):
     assert_geodataframe_equal(df, pq_df)
 
 
-def test_parquet_multiple_geom_cols(tmpdir, file_format):
+def test_parquet_multiple_geom_cols(tmpdir, file_format, naturalearth_lowres):
     """If multiple geometry columns are present when written to parquet,
     they should all be returned as such when read from parquet.
     """
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
     df["geom2"] = df.geometry.copy()
 
     filename = os.path.join(str(tmpdir), "test.pq")
@@ -413,13 +407,12 @@ def test_parquet_multiple_geom_cols(tmpdir, file_format):
     assert_geoseries_equal(df.geom2, pq_df.geom2, check_geom_type=True)
 
 
-def test_parquet_missing_metadata(tmpdir):
+def test_parquet_missing_metadata(tmpdir, naturalearth_lowres):
     """Missing geo metadata, such as from a parquet file created
     from a pandas DataFrame, will raise a ValueError.
     """
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     # convert to DataFrame
     df = DataFrame(df)
@@ -473,7 +466,7 @@ def test_parquet_missing_metadata2(tmpdir):
         ),
     ],
 )
-def test_parquet_invalid_metadata(tmpdir, geo_meta, error):
+def test_parquet_invalid_metadata(tmpdir, geo_meta, error, naturalearth_lowres):
     """Has geo metadata with missing required fields will raise a ValueError.
 
     This requires writing the parquet file directly below, so that we can
@@ -482,8 +475,7 @@ def test_parquet_invalid_metadata(tmpdir, geo_meta, error):
 
     from pyarrow import parquet, Table
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     # convert to DataFrame and encode geometry to WKB
     df = DataFrame(df)
@@ -501,14 +493,13 @@ def test_parquet_invalid_metadata(tmpdir, geo_meta, error):
         read_parquet(filename)
 
 
-def test_subset_columns(tmpdir, file_format):
+def test_subset_columns(tmpdir, file_format, naturalearth_lowres):
     """Reading a subset of columns should correctly decode selected geometry
     columns.
     """
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     filename = os.path.join(str(tmpdir), "test.pq")
     writer(df, filename)
@@ -522,14 +513,13 @@ def test_subset_columns(tmpdir, file_format):
         reader(filename, columns=["name"])
 
 
-def test_promote_secondary_geometry(tmpdir, file_format):
+def test_promote_secondary_geometry(tmpdir, file_format, naturalearth_lowres):
     """Reading a subset of columns that does not include the primary geometry
     column should promote the first geometry column present.
     """
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
     df["geom2"] = df.geometry.copy()
 
     filename = os.path.join(str(tmpdir), "test.pq")
@@ -552,13 +542,12 @@ def test_promote_secondary_geometry(tmpdir, file_format):
     )
 
 
-def test_columns_no_geometry(tmpdir, file_format):
+def test_columns_no_geometry(tmpdir, file_format, naturalearth_lowres):
     """Reading a parquet file that is missing all of the geometry columns
     should raise a ValueError"""
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     filename = os.path.join(str(tmpdir), "test.pq")
     writer(df, filename)
@@ -567,15 +556,13 @@ def test_columns_no_geometry(tmpdir, file_format):
         reader(filename, columns=["name"])
 
 
-def test_missing_crs(tmpdir, file_format):
+def test_missing_crs(tmpdir, file_format, naturalearth_lowres):
     """If CRS is `None`, it should be properly handled
     and remain `None` when read from parquet`.
     """
     reader, writer = file_format
 
-    test_dataset = "naturalearth_lowres"
-
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
     df.crs = None
 
     filename = os.path.join(str(tmpdir), "test.pq")
@@ -600,8 +587,8 @@ def test_default_geo_col_writes(tmp_path):
     Version(pyarrow.__version__) >= Version("0.17.0"),
     reason="Feather only supported for pyarrow >= 0.17",
 )
-def test_feather_arrow_version(tmpdir):
-    df = read_file(get_path("naturalearth_lowres"))
+def test_feather_arrow_version(tmpdir, naturalearth_lowres):
+    df = read_file(naturalearth_lowres)
     filename = os.path.join(str(tmpdir), "test.feather")
 
     with pytest.raises(
@@ -610,7 +597,7 @@ def test_feather_arrow_version(tmpdir):
         df.to_feather(filename)
 
 
-def test_fsspec_url():
+def test_fsspec_url(naturalearth_lowres):
     fsspec = pytest.importorskip("fsspec")
     import fsspec.implementations.memory
 
@@ -624,8 +611,7 @@ def test_fsspec_url():
     fsspec.register_implementation("memory", MyMemoryFileSystem, clobber=True)
     memfs = MyMemoryFileSystem(is_set=True)
 
-    test_dataset = "naturalearth_lowres"
-    df = read_file(get_path(test_dataset))
+    df = read_file(naturalearth_lowres)
 
     with memfs.open("data.parquet", "wb") as f:
         df.to_parquet(f)
@@ -642,10 +628,9 @@ def test_fsspec_url():
     )
 
 
-def test_non_fsspec_url_with_storage_options_raises():
+def test_non_fsspec_url_with_storage_options_raises(naturalearth_lowres):
     with pytest.raises(ValueError, match="storage_options"):
-        test_dataset = "naturalearth_lowres"
-        read_parquet(get_path(test_dataset), storage_options={"foo": "bar"})
+        read_parquet(naturalearth_lowres, storage_options={"foo": "bar"})
 
 
 @pytest.mark.skipif(
@@ -874,10 +859,10 @@ def test_read_gdal_files():
     assert_geodataframe_equal(df, expected, check_crs=True)
 
 
-def test_parquet_read_partitioned_dataset(tmpdir):
+def test_parquet_read_partitioned_dataset(tmpdir, naturalearth_lowres):
     # we don't yet explicitly support this (in writing), but for Parquet it
     # works for reading (by relying on pyarrow.read_table)
-    df = read_file(get_path("naturalearth_lowres"))
+    df = read_file(naturalearth_lowres)
 
     # manually create partitioned dataset
     basedir = tmpdir / "partitioned_dataset"
@@ -889,10 +874,10 @@ def test_parquet_read_partitioned_dataset(tmpdir):
     assert_geodataframe_equal(result, df)
 
 
-def test_parquet_read_partitioned_dataset_fsspec(tmpdir):
+def test_parquet_read_partitioned_dataset_fsspec(tmpdir, naturalearth_lowres):
     fsspec = pytest.importorskip("fsspec")
 
-    df = read_file(get_path("naturalearth_lowres"))
+    df = read_file(naturalearth_lowres)
 
     # manually create partitioned dataset
     memfs = fsspec.filesystem("memory")
diff --git a/geopandas/io/tests/test_file.py b/geopandas/io/tests/test_file.py
index 34180e94..5f983774 100644
--- a/geopandas/io/tests/test_file.py
+++ b/geopandas/io/tests/test_file.py
@@ -24,7 +24,7 @@ from geopandas.tests.util import PACKAGE_DIR, validate_boro_df
 try:
     import pyogrio
 
-    PYOGRIO_GE_07 = Version(pyogrio.__version__) > Version("0.6.0")
+    PYOGRIO_GE_07 = Version(pyogrio.__version__) >= Version("0.7.0")
 except ImportError:
     pyogrio = False
     PYOGRIO_GE_07 = False
@@ -65,9 +65,8 @@ def skip_pyogrio_not_supported(engine):
 
 
 @pytest.fixture
-def df_nybb(engine):
-    nybb_path = geopandas.datasets.get_path("nybb")
-    df = read_file(nybb_path, engine=engine)
+def df_nybb(engine, nybb_filename):
+    df = read_file(nybb_filename, engine=engine)
     return df
 
 
@@ -198,9 +197,8 @@ datetime_type_tests = (TEST_DATE, eastern.localize(TEST_DATE))
 @pytest.mark.parametrize("driver,ext", driver_ext_pairs)
 def test_to_file_datetime(tmpdir, driver, ext, time, engine):
     """Test writing a data file with the datetime column type"""
-    if engine == "pyogrio" and time.tzinfo is not None:
-        # TODO
-        pytest.skip("pyogrio doesn't yet support timezones")
+    if engine == "pyogrio" and time.tzinfo is not None and not PYOGRIO_GE_07:
+        pytest.skip("pyogrio < 0.7.0 doesn't support timezones")
     if ext in (".shp", ""):
         pytest.skip(f"Driver corresponding to ext {ext} doesn't support dt fields")
 
@@ -210,23 +208,25 @@ def test_to_file_datetime(tmpdir, driver, ext, time, engine):
     df = GeoDataFrame(
         {"a": [1.0, 2.0], "b": [time, time]}, geometry=[point, point], crs=4326
     )
-    fiona_precision_limit = "ms"
-    df["b"] = df["b"].dt.round(freq=fiona_precision_limit)
+    df["b"] = df["b"].dt.round(freq="ms")
 
     df.to_file(tempfilename, driver=driver, engine=engine)
     df_read = read_file(tempfilename, engine=engine)
 
     assert_geodataframe_equal(df.drop(columns=["b"]), df_read.drop(columns=["b"]))
+    # Check datetime column
+    expected = df["b"]
+    if PANDAS_GE_20:
+        expected = df["b"].dt.as_unit("ms")
+    actual = df_read["b"]
     if df["b"].dt.tz is not None:
         # US/Eastern becomes pytz.FixedOffset(-300) when read from file
-        # so compare fairly in terms of UTC
-        assert_series_equal(
-            df["b"].dt.tz_convert(pytz.utc), df_read["b"].dt.tz_convert(pytz.utc)
-        )
-    else:
-        if engine == "pyogrio" and PANDAS_GE_20:
-            df["b"] = df["b"].astype("datetime64[ms]")
-        assert_series_equal(df["b"], df_read["b"])
+        # as GDAL only models offsets, not timezones.
+        # Compare fair result in terms of UTC instead
+        expected = expected.dt.tz_convert(pytz.utc)
+        actual = actual.dt.tz_convert(pytz.utc)
+
+    assert_series_equal(expected, actual)
 
 
 dt_exts = ["gpkg", "geojson"]
@@ -269,9 +269,6 @@ def test_read_file_datetime_invalid(tmpdir, ext, engine):
 @pytest.mark.parametrize("ext", dt_exts)
 def test_read_file_datetime_out_of_bounds_ns(tmpdir, ext, engine):
     # https://github.com/geopandas/geopandas/issues/2502
-    if ext == "geojson":
-        skip_pyogrio_not_supported(engine)
-
     date_str = "9999-12-31T00:00:00"  # valid to GDAL, not to [ns] format
     tempfilename = write_invalid_date_file(date_str, tmpdir, ext, engine)
     res = read_file(tempfilename)
@@ -295,17 +292,14 @@ def test_read_file_datetime_mixed_offsets(tmpdir):
     df.to_file(tempfilename)
     # check mixed tz don't crash GH2478
     res = read_file(tempfilename)
-    if engine == "fiona":
-        # Convert mixed timezones to UTC equivalent
-        assert is_datetime64_any_dtype(res["date"])
+    # Convert mixed timezones to UTC equivalent
+    assert is_datetime64_any_dtype(res["date"])
+    if engine == "fiona" or (engine == "pyogrio" and PYOGRIO_GE_07):
         if not PANDAS_GE_20:
             utc = pytz.utc
         else:
             utc = datetime.timezone.utc
         assert res["date"].dt.tz == utc
-    else:
-        # old fiona and pyogrio ignore timezones and read as datetimes successfully
-        assert is_datetime64_any_dtype(res["date"])
 
 
 @pytest.mark.parametrize("driver,ext", driver_ext_pairs)
@@ -444,12 +438,12 @@ def test_to_file_schema(tmpdir, df_nybb, engine):
         assert result_schema == schema
 
 
-def test_to_file_crs(tmpdir, engine):
+def test_to_file_crs(tmpdir, engine, nybb_filename):
     """
     Ensure that the file is written according to the crs
     if it is specified
     """
-    df = read_file(geopandas.datasets.get_path("nybb"), engine=engine)
+    df = read_file(nybb_filename, engine=engine)
     tempfilename = os.path.join(str(tmpdir), "crs.shp")
 
     # save correct CRS
@@ -575,8 +569,8 @@ def test_empty_crs(tmpdir, driver, ext, engine):
 NYBB_CRS = "epsg:2263"
 
 
-def test_read_file(engine):
-    df = read_file(geopandas.datasets.get_path("nybb"), engine=engine)
+def test_read_file(engine, nybb_filename):
+    df = read_file(nybb_filename, engine=engine)
     validate_boro_df(df)
     assert df.crs == NYBB_CRS
     expected_columns = ["BoroCode", "BoroName", "Shape_Leng", "Shape_Area"]
@@ -592,7 +586,7 @@ def test_read_file(engine):
         "main/geopandas/tests/data/null_geom.geojson",
         # url to zip file
         "https://raw.githubusercontent.com/geopandas/geopandas/"
-        "main/geopandas/datasets/nybb_16a.zip",
+        "main/geopandas/tests/data/nybb_16a.zip",
         # url to zipfile without extension
         "https://geonode.goosocean.org/download/480",
         # url to web service
@@ -662,11 +656,11 @@ def test_read_file_tempfile(engine):
     temp.close()
 
 
-def test_read_binary_file_fsspec(engine):
+def test_read_binary_file_fsspec(engine, nybb_filename):
     fsspec = pytest.importorskip("fsspec")
     # Remove the zip scheme so fsspec doesn't open as a zipped file,
     # instead we want to read as bytes and let fiona decode it.
-    path = geopandas.datasets.get_path("nybb")[6:]
+    path = nybb_filename[6:]
     with fsspec.open(path, "rb") as f:
         gdf = read_file(f, engine=engine)
         assert isinstance(gdf, geopandas.GeoDataFrame)
@@ -679,10 +673,10 @@ def test_read_text_file_fsspec(file_path, engine):
         assert isinstance(gdf, geopandas.GeoDataFrame)
 
 
-def test_infer_zipped_file(engine):
+def test_infer_zipped_file(engine, nybb_filename):
     # Remove the zip scheme so that the test for a zipped file can
     # check it and add it back.
-    path = geopandas.datasets.get_path("nybb")[6:]
+    path = nybb_filename[6:]
     gdf = read_file(path, engine=engine)
     assert isinstance(gdf, geopandas.GeoDataFrame)
 
@@ -697,15 +691,14 @@ def test_infer_zipped_file(engine):
     assert isinstance(gdf, geopandas.GeoDataFrame)
 
 
-def test_allow_legacy_gdal_path(engine):
+def test_allow_legacy_gdal_path(engine, nybb_filename):
     # Construct a GDAL-style zip path.
-    path = "/vsizip/" + geopandas.datasets.get_path("nybb")[6:]
+    path = "/vsizip/" + nybb_filename[6:]
     gdf = read_file(path, engine=engine)
     assert isinstance(gdf, geopandas.GeoDataFrame)
 
 
-def test_read_file_filtered__bbox(df_nybb, engine):
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def test_read_file_filtered__bbox(df_nybb, engine, nybb_filename):
     bbox = (
         1031051.7879884212,
         224272.49231459625,
@@ -717,8 +710,7 @@ def test_read_file_filtered__bbox(df_nybb, engine):
     assert_geodataframe_equal(filtered_df, expected.reset_index(drop=True))
 
 
-def test_read_file_filtered__bbox__polygon(df_nybb, engine):
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def test_read_file_filtered__bbox__polygon(df_nybb, engine, nybb_filename):
     bbox = box(
         1031051.7879884212, 224272.49231459625, 1047224.3104931959, 244317.30894023244
     )
@@ -727,14 +719,12 @@ def test_read_file_filtered__bbox__polygon(df_nybb, engine):
     assert_geodataframe_equal(filtered_df, expected.reset_index(drop=True))
 
 
-def test_read_file_filtered__rows(df_nybb, engine):
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def test_read_file_filtered__rows(df_nybb, engine, nybb_filename):
     filtered_df = read_file(nybb_filename, rows=1, engine=engine)
     assert_geodataframe_equal(filtered_df, df_nybb.iloc[[0], :])
 
 
-def test_read_file_filtered__rows_slice(df_nybb, engine):
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def test_read_file_filtered__rows_slice(df_nybb, engine, nybb_filename):
     filtered_df = read_file(nybb_filename, rows=slice(1, 3), engine=engine)
     assert_geodataframe_equal(filtered_df, df_nybb.iloc[1:3, :].reset_index(drop=True))
 
@@ -742,8 +732,7 @@ def test_read_file_filtered__rows_slice(df_nybb, engine):
 @pytest.mark.filterwarnings(
     "ignore:Layer does not support OLC_FASTFEATURECOUNT:RuntimeWarning"
 )  # for the slice with -1
-def test_read_file_filtered__rows_bbox(df_nybb, engine):
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def test_read_file_filtered__rows_bbox(df_nybb, engine, nybb_filename):
     bbox = (
         1031051.7879884212,
         224272.49231459625,
@@ -782,16 +771,14 @@ def test_read_file_filtered__rows_bbox(df_nybb, engine):
         )
 
 
-def test_read_file_filtered_rows_invalid(engine):
+def test_read_file_filtered_rows_invalid(engine, nybb_filename):
     with pytest.raises(TypeError):
-        read_file(
-            geopandas.datasets.get_path("nybb"), rows="not_a_slice", engine=engine
-        )
+        read_file(nybb_filename, rows="not_a_slice", engine=engine)
 
 
-def test_read_file__ignore_geometry(engine):
+def test_read_file__ignore_geometry(engine, naturalearth_lowres):
     pdf = geopandas.read_file(
-        geopandas.datasets.get_path("naturalearth_lowres"),
+        naturalearth_lowres,
         ignore_geometry=True,
         engine=engine,
     )
@@ -799,10 +786,10 @@ def test_read_file__ignore_geometry(engine):
     assert isinstance(pdf, pd.DataFrame) and not isinstance(pdf, geopandas.GeoDataFrame)
 
 
-def test_read_file__ignore_all_fields(engine):
+def test_read_file__ignore_all_fields(engine, naturalearth_lowres):
     skip_pyogrio_not_supported(engine)  # pyogrio has "columns" keyword instead
     gdf = geopandas.read_file(
-        geopandas.datasets.get_path("naturalearth_lowres"),
+        naturalearth_lowres,
         ignore_fields=["pop_est", "continent", "name", "iso_a3", "gdp_md_est"],
         engine="fiona",
     )
@@ -836,10 +823,10 @@ def test_read_csv_dtype(tmpdir, df_nybb):
     assert pdf.geometry.dtype == "geometry"
 
 
-def test_read_file__where_filter(engine):
+def test_read_file__where_filter(engine, naturalearth_lowres):
     if FIONA_GE_19 or engine == "pyogrio":
         gdf = geopandas.read_file(
-            geopandas.datasets.get_path("naturalearth_lowres"),
+            naturalearth_lowres,
             where="continent='Africa'",
             engine=engine,
         )
@@ -847,26 +834,25 @@ def test_read_file__where_filter(engine):
     else:
         with pytest.raises(NotImplementedError):
             geopandas.read_file(
-                geopandas.datasets.get_path("naturalearth_lowres"),
+                naturalearth_lowres,
                 where="continent='Africa'",
                 engine="fiona",
             )
 
 
 @PYOGRIO_MARK
-def test_read_file__columns():
+def test_read_file__columns(naturalearth_lowres):
     # TODO: this is only support for pyogrio, but we could mimic it for fiona as well
     gdf = geopandas.read_file(
-        geopandas.datasets.get_path("naturalearth_lowres"),
+        naturalearth_lowres,
         columns=["name", "pop_est"],
         engine="pyogrio",
     )
     assert gdf.columns.tolist() == ["name", "pop_est", "geometry"]
 
 
-def test_read_file_filtered_with_gdf_boundary(df_nybb, engine):
+def test_read_file_filtered_with_gdf_boundary(df_nybb, engine, nybb_filename):
     full_df_shape = df_nybb.shape
-    nybb_filename = geopandas.datasets.get_path("nybb")
     bbox = geopandas.GeoDataFrame(
         geometry=[
             box(
@@ -884,11 +870,13 @@ def test_read_file_filtered_with_gdf_boundary(df_nybb, engine):
     assert filtered_df_shape == (2, 5)
 
 
-def test_read_file_filtered_with_gdf_boundary__mask(df_nybb, engine):
+def test_read_file_filtered_with_gdf_boundary__mask(
+    df_nybb, engine, naturalearth_lowres, naturalearth_cities
+):
     skip_pyogrio_not_supported(engine)
-    gdf_mask = geopandas.read_file(geopandas.datasets.get_path("naturalearth_lowres"))
+    gdf_mask = geopandas.read_file(naturalearth_lowres)
     gdf = geopandas.read_file(
-        geopandas.datasets.get_path("naturalearth_cities"),
+        naturalearth_cities,
         mask=gdf_mask[gdf_mask.continent == "Africa"],
         engine=engine,
     )
@@ -896,10 +884,11 @@ def test_read_file_filtered_with_gdf_boundary__mask(df_nybb, engine):
     assert filtered_df_shape == (57, 2)
 
 
-def test_read_file_filtered_with_gdf_boundary__mask__polygon(df_nybb, engine):
+def test_read_file_filtered_with_gdf_boundary__mask__polygon(
+    df_nybb, engine, nybb_filename
+):
     skip_pyogrio_not_supported(engine)
     full_df_shape = df_nybb.shape
-    nybb_filename = geopandas.datasets.get_path("nybb")
     mask = box(
         1031051.7879884212, 224272.49231459625, 1047224.3104931959, 244317.30894023244
     )
@@ -909,10 +898,11 @@ def test_read_file_filtered_with_gdf_boundary__mask__polygon(df_nybb, engine):
     assert filtered_df_shape == (2, 5)
 
 
-def test_read_file_filtered_with_gdf_boundary_mismatched_crs(df_nybb, engine):
+def test_read_file_filtered_with_gdf_boundary_mismatched_crs(
+    df_nybb, engine, nybb_filename
+):
     skip_pyogrio_not_supported(engine)
     full_df_shape = df_nybb.shape
-    nybb_filename = geopandas.datasets.get_path("nybb")
     bbox = geopandas.GeoDataFrame(
         geometry=[
             box(
@@ -931,10 +921,11 @@ def test_read_file_filtered_with_gdf_boundary_mismatched_crs(df_nybb, engine):
     assert filtered_df_shape == (2, 5)
 
 
-def test_read_file_filtered_with_gdf_boundary_mismatched_crs__mask(df_nybb, engine):
+def test_read_file_filtered_with_gdf_boundary_mismatched_crs__mask(
+    df_nybb, engine, nybb_filename
+):
     skip_pyogrio_not_supported(engine)
     full_df_shape = df_nybb.shape
-    nybb_filename = geopandas.datasets.get_path("nybb")
     mask = geopandas.GeoDataFrame(
         geometry=[
             box(
@@ -983,9 +974,9 @@ def test_read_file_empty_shapefile(tmpdir, engine):
     assert all(empty.columns == ["A", "Z", "geometry"])
 
 
-def test_read_file_privacy(tmpdir, df_nybb):
+def test_read_file_privacy(tmpdir, df_nybb, nybb_filename):
     with pytest.warns(FutureWarning):
-        geopandas.io.file.read_file(geopandas.datasets.get_path("nybb"))
+        geopandas.io.file.read_file(nybb_filename)
 
 
 class FileNumber(object):
@@ -1154,7 +1145,7 @@ def test_write_index_to_file(tmpdir, df_points, driver, ext, engine):
     # index as string
     df_p = df_points.copy()
     df = GeoDataFrame(df_p["value1"], geometry=df_p.geometry)
-    df.index = pd.TimedeltaIndex(range(len(df)), "days")
+    df.index = pd.to_timedelta(range(len(df)), unit="days")
     # TODO: TimedeltaIndex is an invalid field type
     df.index = df.index.astype(str)
     do_checks(df, index_is_used=True)
@@ -1162,7 +1153,7 @@ def test_write_index_to_file(tmpdir, df_points, driver, ext, engine):
     # unnamed DatetimeIndex
     df_p = df_points.copy()
     df = GeoDataFrame(df_p["value1"], geometry=df_p.geometry)
-    df.index = pd.TimedeltaIndex(range(len(df)), "days") + pd.DatetimeIndex(
+    df.index = pd.to_timedelta(range(len(df)), unit="days") + pd.to_datetime(
         ["1999-12-27"] * len(df)
     )
     if driver == "ESRI Shapefile":
@@ -1201,7 +1192,7 @@ def test_multiple_geom_cols_error(tmpdir, df_nybb):
 
 @PYOGRIO_MARK
 @FIONA_MARK
-def test_option_io_engine():
+def test_option_io_engine(nybb_filename):
     try:
         geopandas.options.io_engine = "pyogrio"
 
@@ -1212,7 +1203,6 @@ def test_option_io_engine():
         orig = fiona.supported_drivers["ESRI Shapefile"]
         fiona.supported_drivers["ESRI Shapefile"] = "w"
 
-        nybb_filename = geopandas.datasets.get_path("nybb")
         _ = geopandas.read_file(nybb_filename)
     finally:
         fiona.supported_drivers["ESRI Shapefile"] = orig
diff --git a/geopandas/io/tests/test_file_geom_types_drivers.py b/geopandas/io/tests/test_file_geom_types_drivers.py
index fc873dab..d500d964 100644
--- a/geopandas/io/tests/test_file_geom_types_drivers.py
+++ b/geopandas/io/tests/test_file_geom_types_drivers.py
@@ -244,7 +244,14 @@ def geodataframe(request):
     return request.param
 
 
-@pytest.fixture(params=["GeoJSON", "ESRI Shapefile", "GPKG", "SQLite"])
+@pytest.fixture(
+    params=[
+        ("GeoJSON", ".geojson"),
+        ("ESRI Shapefile", ".shp"),
+        ("GPKG", ".gpkg"),
+        ("SQLite", ".sqlite"),
+    ]
+)
 def ogr_driver(request):
     return request.param
 
@@ -260,9 +267,10 @@ def engine(request):
 
 
 def test_to_file_roundtrip(tmpdir, geodataframe, ogr_driver, engine):
-    output_file = os.path.join(str(tmpdir), "output_file")
+    driver, ext = ogr_driver
+    output_file = os.path.join(str(tmpdir), "output_file" + ext)
     write_kwargs = {}
-    if ogr_driver == "SQLite":
+    if driver == "SQLite":
         write_kwargs["spatialite"] = True
 
         # This if statement can be removed once minimal fiona version >= 1.8.20
@@ -285,22 +293,20 @@ def test_to_file_roundtrip(tmpdir, geodataframe, ogr_driver, engine):
         ):
             write_kwargs["geometry_type"] = "Point Z"
 
-    expected_error = _expected_error_on(geodataframe, ogr_driver)
+    expected_error = _expected_error_on(geodataframe, driver)
     if expected_error:
         with pytest.raises(
             RuntimeError, match="Failed to write record|Could not add feature to layer"
         ):
             geodataframe.to_file(
-                output_file, driver=ogr_driver, engine=engine, **write_kwargs
+                output_file, driver=driver, engine=engine, **write_kwargs
             )
     else:
-        geodataframe.to_file(
-            output_file, driver=ogr_driver, engine=engine, **write_kwargs
-        )
+        geodataframe.to_file(output_file, driver=driver, engine=engine, **write_kwargs)
 
         reloaded = geopandas.read_file(output_file, engine=engine)
 
-        if ogr_driver == "GeoJSON" and engine == "pyogrio":
+        if driver == "GeoJSON" and engine == "pyogrio":
             # For GeoJSON files, the int64 column comes back as int32
             reloaded["a"] = reloaded["a"].astype("int64")
 
diff --git a/geopandas/io/tests/test_sql.py b/geopandas/io/tests/test_sql.py
index a072a481..8a5a7fc5 100644
--- a/geopandas/io/tests/test_sql.py
+++ b/geopandas/io/tests/test_sql.py
@@ -26,9 +26,8 @@ except ImportError:
 
 
 @pytest.fixture
-def df_nybb():
-    nybb_path = geopandas.datasets.get_path("nybb")
-    df = read_file(nybb_path)
+def df_nybb(nybb_filename):
+    df = read_file(nybb_filename)
     return df
 
 
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.VERSION.txt b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.VERSION.txt
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.VERSION.txt
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.VERSION.txt
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.cpg b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.cpg
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.cpg
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.cpg
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.dbf b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.dbf
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.dbf
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.dbf
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.prj b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.prj
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.prj
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.prj
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.shp b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.shp
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.shp
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.shp
diff --git a/geopandas/datasets/naturalearth_cities/naturalearth_cities.shx b/geopandas/tests/data/naturalearth_cities/naturalearth_cities.shx
similarity index 100%
rename from geopandas/datasets/naturalearth_cities/naturalearth_cities.shx
rename to geopandas/tests/data/naturalearth_cities/naturalearth_cities.shx
diff --git a/geopandas/datasets/naturalearth_lowres/naturalearth_lowres.cpg b/geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.cpg
similarity index 100%
rename from geopandas/datasets/naturalearth_lowres/naturalearth_lowres.cpg
rename to geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.cpg
diff --git a/geopandas/datasets/naturalearth_lowres/naturalearth_lowres.dbf b/geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.dbf
similarity index 100%
rename from geopandas/datasets/naturalearth_lowres/naturalearth_lowres.dbf
rename to geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.dbf
diff --git a/geopandas/datasets/naturalearth_lowres/naturalearth_lowres.prj b/geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.prj
similarity index 100%
rename from geopandas/datasets/naturalearth_lowres/naturalearth_lowres.prj
rename to geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.prj
diff --git a/geopandas/datasets/naturalearth_lowres/naturalearth_lowres.shp b/geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.shp
similarity index 100%
rename from geopandas/datasets/naturalearth_lowres/naturalearth_lowres.shp
rename to geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.shp
diff --git a/geopandas/datasets/naturalearth_lowres/naturalearth_lowres.shx b/geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.shx
similarity index 100%
rename from geopandas/datasets/naturalearth_lowres/naturalearth_lowres.shx
rename to geopandas/tests/data/naturalearth_lowres/naturalearth_lowres.shx
diff --git a/geopandas/datasets/nybb_16a.zip b/geopandas/tests/data/nybb_16a.zip
similarity index 100%
rename from geopandas/datasets/nybb_16a.zip
rename to geopandas/tests/data/nybb_16a.zip
diff --git a/geopandas/tests/test_array.py b/geopandas/tests/test_array.py
index 20d4f53c..34ae3f74 100644
--- a/geopandas/tests/test_array.py
+++ b/geopandas/tests/test_array.py
@@ -301,9 +301,9 @@ def test_as_array():
         ("geom_almost_equals", (3,)),
     ],
 )
-@pytest.mark.filterwarnings(
-    r"ignore:The \'almost_equals\(\)\' method is deprecated"
-)  # filter required for attr=geom_almost_equals only
+# filters required for attr=geom_almost_equals only
+@pytest.mark.filterwarnings(r"ignore:The \'geom_almost_equals\(\)\' method is deprecat")
+@pytest.mark.filterwarnings(r"ignore:The \'almost_equals\(\)\' method is deprecated")
 def test_predicates_vector_scalar(attr, args):
     na_value = False
 
@@ -343,9 +343,9 @@ def test_predicates_vector_scalar(attr, args):
         ("geom_almost_equals", (3,)),
     ],
 )
-@pytest.mark.filterwarnings(
-    r"ignore:The \'almost_equals\(\)\' method is deprecated"
-)  # filter required for attr=geom_almost_equals only
+# filters required for attr=geom_almost_equals only
+@pytest.mark.filterwarnings(r"ignore:The \'geom_almost_equals\(\)\' method is deprecat")
+@pytest.mark.filterwarnings(r"ignore:The \'almost_equals\(\)\' method is deprecated")
 def test_predicates_vector_vector(attr, args):
     na_value = False
     empty_value = True if attr == "disjoint" else False
@@ -665,7 +665,21 @@ def test_unary_union():
         shapely.geometry.Polygon([(0, 0), (1, 0), (1, 1)]),
     ]
     G = from_shapely(geoms)
-    u = G.unary_union()
+    with pytest.warns(FutureWarning, match="The 'unary_union' attribute is deprecated"):
+        u = G.unary_union()
+
+    expected = shapely.geometry.Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
+    assert u.equals(expected)
+    assert u.equals(G.union_all())
+
+
+def test_union_all():
+    geoms = [
+        shapely.geometry.Polygon([(0, 0), (0, 1), (1, 1)]),
+        shapely.geometry.Polygon([(0, 0), (1, 0), (1, 1)]),
+    ]
+    G = from_shapely(geoms)
+    u = G.union_all()
 
     expected = shapely.geometry.Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
     assert u.equals(expected)
diff --git a/geopandas/tests/test_crs.py b/geopandas/tests/test_crs.py
index e2c7b13f..ed49834b 100644
--- a/geopandas/tests/test_crs.py
+++ b/geopandas/tests/test_crs.py
@@ -7,7 +7,7 @@ import pyproj
 import pytest
 from shapely.geometry import Point, Polygon, LineString
 
-from geopandas import GeoSeries, GeoDataFrame, points_from_xy, datasets, read_file
+from geopandas import GeoSeries, GeoDataFrame, points_from_xy, read_file
 from geopandas.array import from_shapely, from_wkb, from_wkt, GeometryArray
 from geopandas.testing import assert_geodataframe_equal
 
@@ -83,6 +83,9 @@ def test_to_crs_dimension_z():
     assert result.has_z.all()
 
 
+# pyproj + numpy 1.25 trigger warning for single-element array -> recommdation is to
+# ignore the warning for now (https://github.com/pyproj4/pyproj/issues/1307)
+@pytest.mark.filterwarnings("ignore:Conversion of an array with:DeprecationWarning")
 def test_to_crs_dimension_mixed():
     s = GeoSeries([Point(1, 2), LineString([(1, 2, 3), (4, 5, 6)])], crs=2056)
     result = s.to_crs(epsg=4326)
@@ -151,6 +154,9 @@ def test_transform2(epsg4326, epsg26918):
     assert_geodataframe_equal(df, utm, check_less_precise=True, check_crs=False)
 
 
+# pyproj + numpy 1.25 trigger warning for single-element array -> recommdation is to
+# ignore the warning for now (https://github.com/pyproj4/pyproj/issues/1307)
+@pytest.mark.filterwarnings("ignore:Conversion of an array with:DeprecationWarning")
 def test_crs_axis_order__always_xy():
     df = GeoDataFrame(geometry=[Point(-1683723, 6689139)], crs="epsg:26918")
     lonlat = df.to_crs("epsg:4326")
@@ -420,8 +426,7 @@ class TestGeometryArrayCRS:
             df = GeoDataFrame()
             df.crs = 4326
 
-    def test_read_file(self):
-        nybb_filename = datasets.get_path("nybb")
+    def test_read_file(self, nybb_filename):
         df = read_file(nybb_filename)
         assert df.crs == pyproj.CRS(2263)
         assert df.geometry.crs == pyproj.CRS(2263)
diff --git a/geopandas/tests/test_datasets.py b/geopandas/tests/test_datasets.py
index 2b4b14a9..09dde905 100644
--- a/geopandas/tests/test_datasets.py
+++ b/geopandas/tests/test_datasets.py
@@ -5,8 +5,11 @@ import pytest
 
 
 @pytest.mark.parametrize(
-    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb"]
+    "test_dataset", ["naturalearth_lowres", "naturalearth_cities", "nybb", "foo"]
 )
 def test_read_paths(test_dataset):
-    with pytest.warns(FutureWarning, match="The geopandas.dataset module is"):
+    with pytest.raises(
+        AttributeError,
+        match=r"The geopandas\.dataset has been deprecated and was removed",
+    ):
         assert isinstance(read_file(get_path(test_dataset)), GeoDataFrame)
diff --git a/geopandas/tests/test_dissolve.py b/geopandas/tests/test_dissolve.py
index bcf1869e..68412248 100644
--- a/geopandas/tests/test_dissolve.py
+++ b/geopandas/tests/test_dissolve.py
@@ -14,8 +14,7 @@ from geopandas.testing import assert_geodataframe_equal, geom_almost_equals
 
 
 @pytest.fixture
-def nybb_polydf():
-    nybb_filename = geopandas.datasets.get_path("nybb")
+def nybb_polydf(nybb_filename):
     nybb_polydf = read_file(nybb_filename)
     nybb_polydf = nybb_polydf[["geometry", "BoroName", "BoroCode"]]
     nybb_polydf = nybb_polydf.rename(columns={"geometry": "myshapes"})
@@ -32,7 +31,7 @@ def merged_shapes(nybb_polydf):
     manhattan_bronx = nybb_polydf.loc[3:4]
     others = nybb_polydf.loc[0:2]
 
-    collapsed = [others.geometry.unary_union, manhattan_bronx.geometry.unary_union]
+    collapsed = [others.geometry.union_all(), manhattan_bronx.geometry.union_all()]
     merged_shapes = GeoDataFrame(
         {"myshapes": collapsed},
         geometry="myshapes",
@@ -152,7 +151,7 @@ def test_dissolve_none(nybb_polydf):
     test = nybb_polydf.dissolve(by=None)
     expected = GeoDataFrame(
         {
-            nybb_polydf.geometry.name: [nybb_polydf.geometry.unary_union],
+            nybb_polydf.geometry.name: [nybb_polydf.geometry.union_all()],
             "BoroName": ["Staten Island"],
             "BoroCode": [5],
             "manhattan_bronx": [5],
@@ -167,7 +166,7 @@ def test_dissolve_none_mean(nybb_polydf):
     test = nybb_polydf.dissolve(aggfunc="mean", numeric_only=True)
     expected = GeoDataFrame(
         {
-            nybb_polydf.geometry.name: [nybb_polydf.geometry.unary_union],
+            nybb_polydf.geometry.name: [nybb_polydf.geometry.union_all()],
             "BoroCode": [3.0],
             "manhattan_bronx": [5.4],
         },
diff --git a/geopandas/tests/test_explore.py b/geopandas/tests/test_explore.py
index 9e134a7b..111c736f 100644
--- a/geopandas/tests/test_explore.py
+++ b/geopandas/tests/test_explore.py
@@ -19,18 +19,27 @@ BRANCA_05 = Version(branca.__version__) > Version("0.4.2")
 FOLIUM_G_014 = Version(folium.__version__) > Version("0.14.0")
 
 
+@pytest.fixture(scope="class")
+def _setup_class_test_explore(
+    nybb_filename, naturalearth_lowres, naturalearth_cities, request
+):
+    request.cls.nybb = gpd.read_file(nybb_filename)
+    request.cls.world = gpd.read_file(naturalearth_lowres)
+    request.cls.cities = gpd.read_file(naturalearth_cities)
+    request.cls.chicago = gpd.read_file(geodatasets.get_path("geoda.chicago_commpop"))
+    request.cls.world["range"] = range(len(request.cls.world))
+    request.cls.missing = request.cls.world.copy()
+    np.random.seed(42)
+    request.cls.missing.loc[
+        np.random.choice(request.cls.missing.index, 40), "continent"
+    ] = np.nan
+    request.cls.missing.loc[
+        np.random.choice(request.cls.missing.index, 40), "pop_est"
+    ] = np.nan
+
+
+@pytest.mark.usefixtures("_setup_class_test_explore")
 class TestExplore:
-    def setup_method(self):
-        self.nybb = gpd.read_file(gpd.datasets.get_path("nybb"))
-        self.world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
-        self.cities = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
-        self.chicago = gpd.read_file(geodatasets.get_path("geoda.chicago_commpop"))
-        self.world["range"] = range(len(self.world))
-        self.missing = self.world.copy()
-        np.random.seed(42)
-        self.missing.loc[np.random.choice(self.missing.index, 40), "continent"] = np.nan
-        self.missing.loc[np.random.choice(self.missing.index, 40), "pop_est"] = np.nan
-
     def _fetch_map_string(self, m):
         out = m._parent.render()
         out_str = "".join(out.split())
diff --git a/geopandas/tests/test_geodataframe.py b/geopandas/tests/test_geodataframe.py
index ea56ebeb..a325aff9 100644
--- a/geopandas/tests/test_geodataframe.py
+++ b/geopandas/tests/test_geodataframe.py
@@ -46,12 +46,13 @@ def how(request):
     return request.param
 
 
+@pytest.mark.usefixtures("_setup_class_nybb_filename")
 class TestDataFrame:
     def setup_method(self):
         N = 10
-
-        nybb_filename = geopandas.datasets.get_path("nybb")
-        self.df = read_file(nybb_filename)
+        # self.nybb_filename attached via _setup_class_nybb_filename
+        self.df = read_file(self.nybb_filename)
+        # TODO re-write instance variables to be fixtures
         self.tempdir = tempfile.mkdtemp()
         self.crs = "epsg:4326"
         self.df2 = GeoDataFrame(
@@ -363,6 +364,21 @@ class TestDataFrame:
         with pytest.raises(AttributeError, match=msg_geo_col_missing):
             df.geometry
 
+    def test_active_geometry_name(self):
+        # default single active called "geometry"
+        assert self.df.active_geometry_name == "geometry"
+
+        # one GeoSeries, not active
+        no_active = GeoDataFrame({"foo": self.df.BoroName, "bar": self.df.geometry})
+        assert no_active.active_geometry_name is None
+        assert no_active.set_geometry("bar").active_geometry_name == "bar"
+
+        # multiple, none active
+        multiple = GeoDataFrame({"foo": self.df.geometry, "bar": self.df.geometry})
+        assert multiple.active_geometry_name is None
+        assert multiple.set_geometry("foo").active_geometry_name == "foo"
+        assert multiple.set_geometry("bar").active_geometry_name == "bar"
+
     def test_align(self):
         df = self.df2
 
@@ -588,9 +604,8 @@ class TestDataFrame:
         df = GeoDataFrame.from_dict(data, geometry="location")
         assert df._geometry_column_name == "location"
 
-    def test_from_features(self):
+    def test_from_features(self, nybb_filename):
         fiona = pytest.importorskip("fiona")
-        nybb_filename = geopandas.datasets.get_path("nybb")
         with fiona.open(nybb_filename) as f:
             features = list(f)
             crs = f.crs_wkt
@@ -965,13 +980,13 @@ class TestDataFrame:
 
     @pytest.mark.parametrize("how", ["left", "inner", "right"])
     @pytest.mark.parametrize("predicate", ["intersects", "within", "contains"])
-    def test_sjoin(self, how, predicate):
+    def test_sjoin(self, how, predicate, naturalearth_cities, naturalearth_lowres):
         """
         Basic test for availability of the GeoDataFrame method. Other
         sjoin tests are located in /tools/tests/test_sjoin.py
         """
-        left = read_file(geopandas.datasets.get_path("naturalearth_cities"))
-        right = read_file(geopandas.datasets.get_path("naturalearth_lowres"))
+        left = read_file(naturalearth_cities)
+        right = read_file(naturalearth_lowres)
 
         expected = geopandas.sjoin(left, right, how=how, predicate=predicate)
         result = left.sjoin(right, how=how, predicate=predicate)
@@ -981,13 +996,15 @@ class TestDataFrame:
     @pytest.mark.parametrize("max_distance", [None, 1])
     @pytest.mark.parametrize("distance_col", [None, "distance"])
     @pytest.mark.filterwarnings("ignore:Geometry is in a geographic CRS:UserWarning")
-    def test_sjoin_nearest(self, how, max_distance, distance_col):
+    def test_sjoin_nearest(
+        self, how, max_distance, distance_col, naturalearth_cities, naturalearth_lowres
+    ):
         """
         Basic test for availability of the GeoDataFrame method. Other
         sjoin tests are located in /tools/tests/test_sjoin.py
         """
-        left = read_file(geopandas.datasets.get_path("naturalearth_cities"))
-        right = read_file(geopandas.datasets.get_path("naturalearth_lowres"))
+        left = read_file(naturalearth_cities)
+        right = read_file(naturalearth_lowres)
 
         expected = geopandas.sjoin_nearest(
             left, right, how=how, max_distance=max_distance, distance_col=distance_col
@@ -997,13 +1014,13 @@ class TestDataFrame:
         )
         assert_geodataframe_equal(result, expected)
 
-    def test_clip(self):
+    def test_clip(self, naturalearth_cities, naturalearth_lowres):
         """
         Basic test for availability of the GeoDataFrame method. Other
         clip tests are located in /tools/tests/test_clip.py
         """
-        left = read_file(geopandas.datasets.get_path("naturalearth_cities"))
-        world = read_file(geopandas.datasets.get_path("naturalearth_lowres"))
+        left = read_file(naturalearth_cities)
+        world = read_file(naturalearth_lowres)
         south_america = world[world["continent"] == "South America"]
 
         expected = geopandas.clip(left, south_america)
@@ -1388,8 +1405,7 @@ class TestConstructor:
         assert gdf._geometry_column_name == ("geometry", "", "")
         assert gdf.geometry.name == ("geometry", "", "")
 
-    def test_assign_cols_using_index(self):
-        nybb_filename = geopandas.datasets.get_path("nybb")
+    def test_assign_cols_using_index(self, nybb_filename):
         df = read_file(nybb_filename)
         other_df = pd.DataFrame({"foo": range(5), "bar": range(5)})
         expected = pd.concat([df, other_df], axis=1)
diff --git a/geopandas/tests/test_geom_methods.py b/geopandas/tests/test_geom_methods.py
index ca7792f9..72f75f77 100644
--- a/geopandas/tests/test_geom_methods.py
+++ b/geopandas/tests/test_geom_methods.py
@@ -183,7 +183,7 @@ class TestGeomMethods:
         fcmp = assert_series_equal
         self._test_unary(op, expected, a, fcmp)
 
-    def _test_unary_topological(self, op, expected, a):
+    def _test_unary_topological(self, op, expected, a, method=False):
         if isinstance(expected, GeoPandasBase):
             fcmp = assert_geoseries_equal
         else:
@@ -191,7 +191,7 @@ class TestGeomMethods:
             def fcmp(a, b):
                 assert a.equals(b)
 
-        self._test_unary(op, expected, a, fcmp)
+        self._test_unary(op, expected, a, fcmp, method=method)
 
     def _test_binary_topological(self, op, expected, a, b, *args, **kwargs):
         """Tests for 'intersection', 'union', 'symmetric_difference', etc."""
@@ -294,14 +294,20 @@ class TestGeomMethods:
                 result = getattr(gdf_left, op)(gdf_right, *args, **kwargs)
                 fcmp(result, expected)
 
-    def _test_unary(self, op, expected, a, fcmp):
+    def _test_unary(self, op, expected, a, fcmp, method=False):
         # GeoSeries, (GeoSeries or geometry)
-        result = getattr(a, op)
+        if method:
+            result = getattr(a, op)()
+        else:
+            result = getattr(a, op)
         fcmp(result, expected)
 
         # GeoDataFrame, (GeoSeries or geometry)
         gdf = self.gdf1.set_geometry(a)
-        result = getattr(gdf, op)
+        if method:
+            result = getattr(gdf, op)()
+        else:
+            result = getattr(gdf, op)
         fcmp(result, expected)
 
     # TODO re-enable for all operations once we use pyproj > 2
@@ -464,30 +470,29 @@ class TestGeomMethods:
         )
         assert_frame_equal(result, expected)
 
-    def test_unary_union(self):
+    def test_union_all(self):
         p1 = self.t1
         p2 = Polygon([(2, 0), (3, 0), (3, 1)])
         expected = unary_union([p1, p2])
         g = GeoSeries([p1, p2])
 
-        self._test_unary_topological("unary_union", expected, g)
+        self._test_unary_topological("union_all", expected, g, method=True)
 
         g2 = GeoSeries([p1, None])
-        self._test_unary_topological("unary_union", p1, g2)
+        self._test_unary_topological("union_all", p1, g2, method=True)
 
-        with pytest.warns(FutureWarning, match="`unary_union` returned None"):
-            g3 = GeoSeries([None, None])
-            assert g3.unary_union is None
+        g3 = GeoSeries([None, None])
+        assert g3.union_all().equals(shapely.GeometryCollection())
 
-    def test_cascaded_union_deprecated(self):
+    def test_unary_union_deprecated(self):
         p1 = self.t1
         p2 = Polygon([(2, 0), (3, 0), (3, 1)])
         g = GeoSeries([p1, p2])
         with pytest.warns(
-            FutureWarning, match="The 'cascaded_union' attribute is deprecated"
+            FutureWarning, match="The 'unary_union' attribute is deprecated"
         ):
-            result = g.cascaded_union
-        assert result == g.unary_union
+            result = g.unary_union
+        assert result == g.union_all()
 
     def test_contains(self):
         expected = [True, False, True, False, False, False, False]
@@ -1249,7 +1254,7 @@ class TestGeomMethods:
     def test_minimum_bounding_circle(self):
         mbc = self.g1.minimum_bounding_circle()
         centers = GeoSeries([Point(0.5, 0.5)] * 2)
-        assert np.all(mbc.centroid.geom_almost_equals(centers, 0.001))
+        assert np.all(mbc.centroid.geom_equals_exact(centers, 0.001))
         assert_series_equal(
             mbc.area,
             Series([1.560723, 1.560723]),
diff --git a/geopandas/tests/test_geoseries.py b/geopandas/tests/test_geoseries.py
index e72a9b66..4ebf2463 100644
--- a/geopandas/tests/test_geoseries.py
+++ b/geopandas/tests/test_geoseries.py
@@ -22,7 +22,7 @@ from shapely.geometry import (
 )
 from shapely.geometry.base import BaseGeometry
 
-from geopandas import GeoSeries, GeoDataFrame, read_file, datasets, clip
+from geopandas import GeoSeries, GeoDataFrame, read_file, clip
 from geopandas.array import GeometryArray, GeometryDtype
 from geopandas.testing import assert_geoseries_equal, geom_almost_equals
 
@@ -362,9 +362,9 @@ class TestSeries:
     def test_to_wkt(self):
         assert_series_equal(pd.Series([self.t1.wkt, self.sq.wkt]), self.g1.to_wkt())
 
-    def test_clip(self):
-        left = read_file(datasets.get_path("naturalearth_cities"))
-        world = read_file(datasets.get_path("naturalearth_lowres"))
+    def test_clip(self, naturalearth_lowres, naturalearth_cities):
+        left = read_file(naturalearth_cities)
+        world = read_file(naturalearth_lowres)
         south_america = world[world["continent"] == "South America"]
 
         expected = clip(left.geometry, south_america)
diff --git a/geopandas/tests/test_op_output_types.py b/geopandas/tests/test_op_output_types.py
index 2d6b37c8..0fce83a8 100644
--- a/geopandas/tests/test_op_output_types.py
+++ b/geopandas/tests/test_op_output_types.py
@@ -284,7 +284,7 @@ def test_expandim_in_groupby_aggregate_multiple_funcs():
     s = GeoSeries.from_xy([0, 1, 2], [0, 1, 3])
 
     def union(s):
-        return s.unary_union
+        return s.union_all()
 
     def total_area(s):
         return s.area.sum()
diff --git a/geopandas/tests/test_overlay.py b/geopandas/tests/test_overlay.py
index 30d24645..8e9dae0d 100644
--- a/geopandas/tests/test_overlay.py
+++ b/geopandas/tests/test_overlay.py
@@ -113,8 +113,8 @@ def test_overlay(dfs_index, how):
 
 
 @pytest.mark.filterwarnings("ignore:GeoSeries crs mismatch:UserWarning")
-def test_overlay_nybb(how):
-    polydf = read_file(geopandas.datasets.get_path("nybb"))
+def test_overlay_nybb(how, nybb_filename):
+    polydf = read_file(nybb_filename)
 
     # The circles have been constructed and saved at the time the expected
     # results were created (exact output of buffer algorithm can slightly
@@ -712,8 +712,8 @@ def test_overlap_make_valid(should_make_valid):
             overlay(df1, df_bowtie, make_valid=should_make_valid)
 
 
-def test_empty_overlay_return_non_duplicated_columns():
-    nybb = geopandas.read_file(geopandas.datasets.get_path("nybb"))
+def test_empty_overlay_return_non_duplicated_columns(nybb_filename):
+    nybb = geopandas.read_file(nybb_filename)
     nybb2 = nybb.copy()
     nybb2.geometry = nybb2.translate(20000000)
 
diff --git a/geopandas/tests/test_pandas_methods.py b/geopandas/tests/test_pandas_methods.py
index 5a0a66ef..16b304c1 100644
--- a/geopandas/tests/test_pandas_methods.py
+++ b/geopandas/tests/test_pandas_methods.py
@@ -632,7 +632,7 @@ def test_groupby(df):
     assert_frame_equal(res, exp)
 
     # applying on the geometry column
-    res = df.groupby("value2")["geometry"].apply(lambda x: x.unary_union)
+    res = df.groupby("value2")["geometry"].apply(lambda x: x.union_all())
 
     exp = GeoSeries(
         [shapely.geometry.MultiPoint([(0, 0), (2, 2)]), Point(1, 1)],
@@ -642,7 +642,7 @@ def test_groupby(df):
     assert_series_equal(res, exp)
 
     # apply on geometry column not resulting in new geometry
-    res = df.groupby("value2")["geometry"].apply(lambda x: x.unary_union.area)
+    res = df.groupby("value2")["geometry"].apply(lambda x: x.union_all().area)
     exp = pd.Series([0.0, 0.0], index=pd.Index([1, 2], name="value2"), name="geometry")
 
     assert_series_equal(res, exp)
diff --git a/geopandas/tests/test_plotting.py b/geopandas/tests/test_plotting.py
index 2477989b..4ecb4ab0 100644
--- a/geopandas/tests/test_plotting.py
+++ b/geopandas/tests/test_plotting.py
@@ -20,7 +20,6 @@ from shapely.geometry import (
 
 
 from geopandas import GeoDataFrame, GeoSeries, read_file
-from geopandas.datasets import get_path
 import geopandas._compat as compat
 from geopandas.plotting import GeoplotAccessor
 
@@ -1068,16 +1067,19 @@ class TestNonuniformGeometryPlotting:
         #     )
 
 
-class TestGeographicAspect:
-    def setup_class(self):
-        pth = get_path("naturalearth_lowres")
-        df = read_file(pth)
-        self.north = df.loc[df.continent == "North America"]
-        self.north_proj = self.north.to_crs("ESRI:102008")
-        bounds = self.north.total_bounds
-        y_coord = np.mean([bounds[1], bounds[3]])
-        self.exp = 1 / np.cos(y_coord * np.pi / 180)
+@pytest.fixture(scope="class")
+def _setup_class_geographic_aspect(naturalearth_lowres, request):
+    """Attach naturalearth_lowres class attribute for unittest style setup_method"""
+    df = read_file(naturalearth_lowres)
+    request.cls.north = df.loc[df.continent == "North America"]
+    request.cls.north_proj = request.cls.north.to_crs("ESRI:102008")
+    bounds = request.cls.north.total_bounds
+    y_coord = np.mean([bounds[1], bounds[3]])
+    request.cls.exp = 1 / np.cos(y_coord * np.pi / 180)
+
 
+@pytest.mark.usefixtures("_setup_class_geographic_aspect")
+class TestGeographicAspect:
     def test_auto(self):
         ax = self.north.geometry.plot()
         assert ax.get_aspect() == self.exp
@@ -1131,6 +1133,9 @@ class TestGeographicAspect:
         assert ax3.get_aspect() == 0.5
 
 
+@pytest.mark.filterwarnings(
+    "ignore:Numba not installed. Using slow pure python version.:UserWarning"
+)
 class TestMapclassifyPlotting:
     @classmethod
     def setup_class(cls):
@@ -1141,31 +1146,40 @@ class TestMapclassifyPlotting:
         cls.mc = mapclassify
         cls.classifiers = list(mapclassify.classifiers.CLASSIFIERS)
         cls.classifiers.remove("UserDefined")
-        pth = get_path("naturalearth_lowres")
-        cls.df = read_file(pth)
-        cls.df["NEGATIVES"] = np.linspace(-10, 10, len(cls.df.index))
-        cls.df["low_vals"] = np.linspace(0, 0.3, cls.df.shape[0])
-        cls.df["mid_vals"] = np.linspace(0.3, 0.7, cls.df.shape[0])
-        cls.df["high_vals"] = np.linspace(0.7, 1.0, cls.df.shape[0])
-        cls.df.loc[cls.df.index[:20:2], "high_vals"] = np.nan
-        cls.nybb = read_file(get_path("nybb"))
-        cls.nybb["vals"] = [0.001, 0.002, 0.003, 0.004, 0.005]
 
-    def test_legend(self):
+    @pytest.fixture
+    def df(self, naturalearth_lowres):
+        # version of naturalearth_lowres for mapclassify plotting tests
+        df = read_file(naturalearth_lowres)
+        df["NEGATIVES"] = np.linspace(-10, 10, len(df.index))
+        df["low_vals"] = np.linspace(0, 0.3, df.shape[0])
+        df["mid_vals"] = np.linspace(0.3, 0.7, df.shape[0])
+        df["high_vals"] = np.linspace(0.7, 1.0, df.shape[0])
+        df.loc[df.index[:20:2], "high_vals"] = np.nan
+        return df
+
+    @pytest.fixture
+    def nybb(self, nybb_filename):
+        # version of nybb for mapclassify plotting tests
+        df = read_file(nybb_filename)
+        df["vals"] = [0.001, 0.002, 0.003, 0.004, 0.005]
+        return df
+
+    def test_legend(self, df):
         with warnings.catch_warnings(record=True) as _:  # don't print warning
             # warning coming from scipy.stats
-            ax = self.df.plot(
+            ax = df.plot(
                 column="pop_est", scheme="QUANTILES", k=3, cmap="OrRd", legend=True
             )
         labels = [t.get_text() for t in ax.get_legend().get_texts()]
         expected = [
             s.split("|")[0][1:-2]
-            for s in str(self.mc.Quantiles(self.df["pop_est"], k=3)).split("\n")[4:]
+            for s in str(self.mc.Quantiles(df["pop_est"], k=3)).split("\n")[4:]
         ]
         assert labels == expected
 
-    def test_bin_labels(self):
-        ax = self.df.plot(
+    def test_bin_labels(self, df):
+        ax = df.plot(
             column="pop_est",
             scheme="QUANTILES",
             k=3,
@@ -1177,9 +1191,9 @@ class TestMapclassifyPlotting:
         expected = ["foo", "bar", "baz"]
         assert labels == expected
 
-    def test_invalid_labels_length(self):
+    def test_invalid_labels_length(self, df):
         with pytest.raises(ValueError):
-            self.df.plot(
+            df.plot(
                 column="pop_est",
                 scheme="QUANTILES",
                 k=3,
@@ -1188,16 +1202,16 @@ class TestMapclassifyPlotting:
                 legend_kwds={"labels": ["foo", "bar"]},
             )
 
-    def test_negative_legend(self):
-        ax = self.df.plot(
+    def test_negative_legend(self, df):
+        ax = df.plot(
             column="NEGATIVES", scheme="FISHER_JENKS", k=3, cmap="OrRd", legend=True
         )
         labels = [t.get_text() for t in ax.get_legend().get_texts()]
         expected = ["-10.00,  -3.41", " -3.41,   3.30", "  3.30,  10.00"]
         assert labels == expected
 
-    def test_fmt(self):
-        ax = self.df.plot(
+    def test_fmt(self, df):
+        ax = df.plot(
             column="NEGATIVES",
             scheme="FISHER_JENKS",
             k=3,
@@ -1209,8 +1223,8 @@ class TestMapclassifyPlotting:
         expected = ["-10,  -3", " -3,   3", "  3,  10"]
         assert labels == expected
 
-    def test_interval(self):
-        ax = self.df.plot(
+    def test_interval(self, df):
+        ax = df.plot(
             column="NEGATIVES",
             scheme="FISHER_JENKS",
             k=3,
@@ -1223,17 +1237,17 @@ class TestMapclassifyPlotting:
         assert labels == expected
 
     @pytest.mark.parametrize("scheme", ["FISHER_JENKS", "FISHERJENKS"])
-    def test_scheme_name_compat(self, scheme):
-        ax = self.df.plot(column="NEGATIVES", scheme=scheme, k=3, legend=True)
+    def test_scheme_name_compat(self, scheme, df):
+        ax = df.plot(column="NEGATIVES", scheme=scheme, k=3, legend=True)
         assert len(ax.get_legend().get_texts()) == 3
 
-    def test_schemes(self):
+    def test_schemes(self, df):
         # test if all available classifiers pass
         for scheme in self.classifiers:
-            self.df.plot(column="pop_est", scheme=scheme, legend=True)
+            df.plot(column="pop_est", scheme=scheme, legend=True)
 
-    def test_classification_kwds(self):
-        ax = self.df.plot(
+    def test_classification_kwds(self, df):
+        ax = df.plot(
             column="pop_est",
             scheme="percentiles",
             k=3,
@@ -1244,21 +1258,19 @@ class TestMapclassifyPlotting:
         labels = [t.get_text() for t in ax.get_legend().get_texts()]
         expected = [
             s.split("|")[0][1:-2]
-            for s in str(self.mc.Percentiles(self.df["pop_est"], pct=[50, 100])).split(
-                "\n"
-            )[4:]
+            for s in str(self.mc.Percentiles(df["pop_est"], pct=[50, 100])).split("\n")[
+                4:
+            ]
         ]
 
         assert labels == expected
 
-    def test_invalid_scheme(self):
+    def test_invalid_scheme(self, df):
         with pytest.raises(ValueError):
             scheme = "invalid_scheme_*#&)(*#"
-            self.df.plot(
-                column="gdp_md_est", scheme=scheme, k=3, cmap="OrRd", legend=True
-            )
+            df.plot(column="gdp_md_est", scheme=scheme, k=3, cmap="OrRd", legend=True)
 
-    def test_cax_legend_passing(self):
+    def test_cax_legend_passing(self, df):
         """Pass a 'cax' argument to 'df.plot(.)', that is valid only if 'ax' is
         passed as well (if not, a new figure is created ad hoc, and 'cax' is
         ignored)
@@ -1269,15 +1281,15 @@ class TestMapclassifyPlotting:
         divider = make_axes_locatable(ax)
         cax = divider.append_axes("right", size="5%", pad=0.1)
         with pytest.raises(ValueError):
-            ax = self.df.plot(column="pop_est", cmap="OrRd", legend=True, cax=cax)
+            ax = df.plot(column="pop_est", cmap="OrRd", legend=True, cax=cax)
 
-    def test_cax_legend_height(self):
+    def test_cax_legend_height(self, df):
         """Pass a cax argument to 'df.plot(.)', the legend location must be
         aligned with those of main plot
         """
         # base case
         with warnings.catch_warnings(record=True) as _:  # don't print warning
-            ax = self.df.plot(column="pop_est", cmap="OrRd", legend=True)
+            ax = df.plot(column="pop_est", cmap="OrRd", legend=True)
         plot_height = _get_ax(ax.get_figure(), "").get_position().height
         legend_height = _get_ax(ax.get_figure(), "<colorbar>").get_position().height
         assert abs(plot_height - legend_height) >= 1e-6
@@ -1288,16 +1300,14 @@ class TestMapclassifyPlotting:
         divider = make_axes_locatable(ax2)
         cax = divider.append_axes("right", size="5%", pad=0.1, label="fixed_colorbar")
         with warnings.catch_warnings(record=True) as _:
-            ax2 = self.df.plot(
-                column="pop_est", cmap="OrRd", legend=True, cax=cax, ax=ax2
-            )
+            ax2 = df.plot(column="pop_est", cmap="OrRd", legend=True, cax=cax, ax=ax2)
         plot_height = _get_ax(fig, "").get_position().height
         legend_height = _get_ax(fig, "fixed_colorbar").get_position().height
         assert abs(plot_height - legend_height) < 1e-6
 
-    def test_empty_bins(self):
+    def test_empty_bins(self, df):
         bins = np.arange(1, 11) / 10
-        ax = self.df.plot(
+        ax = df.plot(
             "low_vals",
             scheme="UserDefined",
             classification_kwds={"bins": bins},
@@ -1346,7 +1356,7 @@ class TestMapclassifyPlotting:
             line.get_markerfacecolor() for line in ax.get_legend().get_lines()
         ] == legend_colors_exp
 
-        ax2 = self.df.plot(
+        ax2 = df.plot(
             "mid_vals",
             scheme="UserDefined",
             classification_kwds={"bins": bins},
@@ -1384,7 +1394,7 @@ class TestMapclassifyPlotting:
             line.get_markerfacecolor() for line in ax2.get_legend().get_lines()
         ] == legend_colors_exp
 
-        ax3 = self.df.plot(
+        ax3 = df.plot(
             "high_vals",
             scheme="UserDefined",
             classification_kwds={"bins": bins},
@@ -1409,8 +1419,8 @@ class TestMapclassifyPlotting:
             line.get_markerfacecolor() for line in ax3.get_legend().get_lines()
         ] == legend_colors_exp
 
-    def test_equally_formatted_bins(self):
-        ax = self.nybb.plot(
+    def test_equally_formatted_bins(self, nybb):
+        ax = nybb.plot(
             "vals",
             scheme="quantiles",
             legend=True,
@@ -1425,7 +1435,7 @@ class TestMapclassifyPlotting:
         ]
         assert labels == expected
 
-        ax2 = self.nybb.plot(
+        ax2 = nybb.plot(
             "vals", scheme="quantiles", legend=True, legend_kwds={"fmt": "{:.3f}"}
         )
         labels = [t.get_text() for t in ax2.get_legend().get_texts()]
diff --git a/geopandas/tests/test_sindex.py b/geopandas/tests/test_sindex.py
index 016f9307..768ab817 100644
--- a/geopandas/tests/test_sindex.py
+++ b/geopandas/tests/test_sindex.py
@@ -15,7 +15,7 @@ from shapely.geometry import (
 )
 
 import geopandas
-from geopandas import GeoDataFrame, GeoSeries, datasets, read_file
+from geopandas import GeoDataFrame, GeoSeries, read_file
 from geopandas import _compat as compat
 
 
@@ -202,12 +202,12 @@ class TestFrameSindex:
         assert old_sindex is new_sindex
 
 
-# Skip to accommodate Shapely geometries being unhashable
+# Skip to accommodate Shapely geometries being unhashable # TODO unskip?
 @pytest.mark.skip
+@pytest.mark.usefixtures("_setup_class_nybb_filename")
 class TestJoinSindex:
     def setup_method(self):
-        nybb_filename = geopandas.datasets.get_path("nybb")
-        self.boros = read_file(nybb_filename)
+        self.boros = read_file(self.nybb_filename)
 
     def test_merge_geo(self):
         # First check that we gets hits from the boros frame.
@@ -845,10 +845,12 @@ class TestShapelyInterface:
             ("touches", (2, 0)),
         ],
     )
-    def test_integration_natural_earth(self, predicate, expected_shape):
+    def test_integration_natural_earth(
+        self, predicate, expected_shape, naturalearth_lowres, naturalearth_cities
+    ):
         """Tests output sizes for the naturalearth datasets."""
-        world = read_file(datasets.get_path("naturalearth_lowres"))
-        capitals = read_file(datasets.get_path("naturalearth_cities"))
+        world = read_file(naturalearth_lowres)
+        capitals = read_file(naturalearth_cities)
 
         res = world.sindex.query(capitals.geometry, predicate)
         assert res.shape == expected_shape
diff --git a/geopandas/tests/util.py b/geopandas/tests/util.py
index 9e7021ef..e21ab963 100644
--- a/geopandas/tests/util.py
+++ b/geopandas/tests/util.py
@@ -13,6 +13,15 @@ from geopandas.testing import (  # noqa: F401
 HERE = os.path.abspath(os.path.dirname(__file__))
 PACKAGE_DIR = os.path.dirname(os.path.dirname(HERE))
 
+_TEST_DATA_DIR = os.path.join(PACKAGE_DIR, "geopandas", "tests", "data")
+_NYBB = "zip://" + os.path.join(_TEST_DATA_DIR, "nybb_16a.zip")
+_NATURALEARTH_CITIES = os.path.join(
+    _TEST_DATA_DIR, "naturalearth_cities", "naturalearth_cities.shp"
+)
+_NATURALEARTH_LOWRES = os.path.join(
+    _TEST_DATA_DIR, "naturalearth_lowres", "naturalearth_lowres.shp"
+)
+
 
 # mock not used here, but the import from here is used in other modules
 try:
diff --git a/geopandas/tools/tests/test_clip.py b/geopandas/tools/tests/test_clip.py
index 6b4958af..8cc51c9d 100644
--- a/geopandas/tools/tests/test_clip.py
+++ b/geopandas/tools/tests/test_clip.py
@@ -136,7 +136,7 @@ def two_line_gdf():
 @pytest.fixture
 def multi_poly_gdf(donut_geometry):
     """Create a multi-polygon GeoDataFrame."""
-    multi_poly = donut_geometry.unary_union
+    multi_poly = donut_geometry.union_all()
     out_df = GeoDataFrame(geometry=GeoSeries(multi_poly), crs="EPSG:3857")
     out_df["attr"] = ["pool"]
     return out_df
@@ -147,7 +147,7 @@ def multi_line(two_line_gdf):
     """Create a multi-line GeoDataFrame.
     This GDF has one multiline and one regular line."""
     # Create a single and multi line object
-    multiline_feat = two_line_gdf.unary_union
+    multiline_feat = two_line_gdf.union_all()
     linec = LineString([(2, 1), (3, 1), (4, 1), (5, 2)])
     out_df = GeoDataFrame(geometry=GeoSeries([multiline_feat, linec]), crs="EPSG:3857")
     out_df["attr"] = ["road", "stream"]
@@ -157,7 +157,7 @@ def multi_line(two_line_gdf):
 @pytest.fixture
 def multi_point(point_gdf):
     """Create a multi-point GeoDataFrame."""
-    multi_point = point_gdf.unary_union
+    multi_point = point_gdf.union_all()
     out_df = GeoDataFrame(
         geometry=GeoSeries(
             [multi_point, Point(2, 5), Point(-11, -14), Point(-10, -12)]
@@ -320,7 +320,7 @@ class TestClipWithSingleRectangleGdf:
         )
         assert clipped.iloc[0].geometry.wkt == clipped_mutltipoint.wkt
         shape_for_points = (
-            box(*mask) if _mask_is_list_like_rectangle(mask) else mask.unary_union
+            box(*mask) if _mask_is_list_like_rectangle(mask) else mask.union_all()
         )
         assert all(clipped.intersects(shape_for_points))
 
diff --git a/geopandas/tools/tests/test_random.py b/geopandas/tools/tests/test_random.py
index 5e09e2a7..5a810d82 100644
--- a/geopandas/tools/tests/test_random.py
+++ b/geopandas/tools/tests/test_random.py
@@ -4,18 +4,38 @@ import geopandas
 
 from geopandas.tools._random import uniform
 
-multipolygons = geopandas.read_file(geopandas.datasets.get_path("nybb")).geometry
-polygons = multipolygons.explode(ignore_index=True).geometry
-multilinestrings = multipolygons.boundary
-linestrings = polygons.boundary
-points = multipolygons.centroid
+
+@pytest.fixture
+def multipolygons(nybb_filename):
+    return geopandas.read_file(nybb_filename).geometry
+
+
+@pytest.fixture
+def polygons(multipolygons):
+    return multipolygons.explode(ignore_index=True).geometry
+
+
+@pytest.fixture
+def multilinestrings(multipolygons):
+    return multipolygons.boundary
+
+
+@pytest.fixture
+def linestrings(polygons):
+    return polygons.boundary
+
+
+@pytest.fixture
+def points(multipolygons):
+    return multipolygons.centroid
 
 
 @pytest.mark.parametrize("size", [10, 100])
 @pytest.mark.parametrize(
-    "geom", [multipolygons[0], polygons[0], multilinestrings[0], linestrings[0]]
+    "geom_fixture", ["multipolygons", "polygons", "multilinestrings", "linestrings"]
 )
-def test_uniform(geom, size):
+def test_uniform(geom_fixture, size, request):
+    geom = request.getfixturevalue(geom_fixture)[0]
     sample = uniform(geom, size=size, rng=1)
     sample_series = (
         geopandas.GeoSeries(sample).explode(index_parts=True).reset_index(drop=True)
@@ -27,13 +47,13 @@ def test_uniform(geom, size):
     assert len(sample_in_geom) == size
 
 
-def test_uniform_unsupported():
+def test_uniform_unsupported(points):
     with pytest.warns(UserWarning, match="Sampling is not supported"):
         sample = uniform(points[0], size=10, rng=1)
     assert sample.is_empty
 
 
-def test_uniform_generator():
+def test_uniform_generator(polygons):
     sample = uniform(polygons[0], size=10, rng=1)
     sample2 = uniform(polygons[0], size=10, rng=1)
     assert sample.equals(sample2)
diff --git a/geopandas/tools/tests/test_sjoin.py b/geopandas/tools/tests/test_sjoin.py
index 7b94fb55..3ddfde50 100644
--- a/geopandas/tools/tests/test_sjoin.py
+++ b/geopandas/tools/tests/test_sjoin.py
@@ -363,10 +363,10 @@ class TestSpatialJoin:
         assert_frame_equal(res, exp, check_index_type=False)
 
 
+@pytest.mark.usefixtures("_setup_class_nybb_filename")
 class TestSpatialJoinNYBB:
     def setup_method(self):
-        nybb_filename = geopandas.datasets.get_path("nybb")
-        self.polydf = read_file(nybb_filename)
+        self.polydf = read_file(self.nybb_filename)
         self.crs = self.polydf.crs
         N = 20
         b = [int(x) for x in self.polydf.total_bounds]
@@ -536,8 +536,8 @@ class TestSpatialJoinNYBB:
         assert sjoin(empty, self.pointdf, how="inner", predicate=predicate).empty
         assert sjoin(empty, self.pointdf, how="left", predicate=predicate).empty
 
-    def test_empty_sjoin_return_duplicated_columns(self):
-        nybb = geopandas.read_file(geopandas.datasets.get_path("nybb"))
+    def test_empty_sjoin_return_duplicated_columns(self, nybb_filename):
+        nybb = geopandas.read_file(nybb_filename)
         nybb2 = nybb.copy()
         nybb2.geometry = nybb2.translate(200000)  # to get non-overlapping
 
@@ -547,21 +547,22 @@ class TestSpatialJoinNYBB:
         assert "BoroCode_left" in result.columns
 
 
-class TestSpatialJoinNaturalEarth:
-    def setup_method(self):
-        world_path = geopandas.datasets.get_path("naturalearth_lowres")
-        cities_path = geopandas.datasets.get_path("naturalearth_cities")
-        self.world = read_file(world_path)
-        self.cities = read_file(cities_path)
+@pytest.fixture
+def world(naturalearth_lowres):
+    return read_file(naturalearth_lowres)
 
-    def test_sjoin_inner(self):
-        # GH637
-        countries = self.world[["geometry", "name"]]
-        countries = countries.rename(columns={"name": "country"})
-        cities_with_country = sjoin(
-            self.cities, countries, how="inner", predicate="intersects"
-        )
-        assert cities_with_country.shape == (213, 4)
+
+@pytest.fixture
+def cities(naturalearth_cities):
+    return read_file(naturalearth_cities)
+
+
+def test_sjoin_inner(world, cities):
+    # GH637
+    countries = world[["geometry", "name"]]
+    countries = countries.rename(columns={"name": "country"})
+    cities_with_country = sjoin(cities, countries, how="inner", predicate="intersects")
+    assert cities_with_country.shape == (213, 4)
 
 
 class TestNearest:
@@ -872,10 +873,10 @@ class TestNearest:
         assert_geodataframe_equal(expected_gdf, joined)
 
     @pytest.mark.filterwarnings("ignore:Geometry is in a geographic CRS")
-    def test_sjoin_nearest_inner(self):
+    def test_sjoin_nearest_inner(self, naturalearth_lowres, naturalearth_cities):
         # check equivalency of left and inner join
-        countries = read_file(geopandas.datasets.get_path("naturalearth_lowres"))
-        cities = read_file(geopandas.datasets.get_path("naturalearth_cities"))
+        countries = read_file(naturalearth_lowres)
+        cities = read_file(naturalearth_cities)
         countries = countries[["geometry", "name"]].rename(columns={"name": "country"})
 
         # default: inner and left give the same result