Repository: googleapis/python-bigquery

Issue:
feat: `list_tables` accepts a `DatasetListItem`
 **Is your feature request related to a problem? Please describe.**

Code:

```python
for dataset in bqclient.list_datasets():
    tables = list(bqclient.list_tables(dataset, max_results=1))
    if len(tables) == 0:
        bqclient.delete_dataset(dataset)
```

Output:

```
Traceback (most recent call last):
  File "2021/04-test-dataset-cleanup/cleanup.py", line 11, in <module>
    tables = len(bqclient.list_tables(dataset, max_results=1))
  File "/Users/swast/miniconda3/envs/scratch/lib/python3.8/site-packages/google/cloud/bigquery/client.py", line 1327, in list_tables
    raise TypeError("dataset must be a Dataset, DatasetReference, or string")
TypeError: dataset must be a Dataset, DatasetReference, or string
```

 **Describe the solution you'd like**

Where `Dataset` or `DatasetReference` is accepted, also accept a `DatasetListItem`.

 **Describe alternatives you've considered**

I know that we created `DatasetListItem.reference`, which I can use, but it'd be a bit more intuitive if I didn't have to.

 **Additional context**

N/A



Discussion:
In addition to `list_tables`, any method that takes a `DatasetReference` but not a `DatasetListItem` should be updated.

Resolving patch:
diff --git a/google/cloud/bigquery/client.py b/google/cloud/bigquery/client.py
--- a/google/cloud/bigquery/client.py
+++ b/google/cloud/bigquery/client.py
@@ -449,6 +449,22 @@ def _create_bqstorage_client(self):
 
         return bigquery_storage.BigQueryReadClient(credentials=self._credentials)
 
+    def _dataset_from_arg(self, dataset):
+        if isinstance(dataset, str):
+            dataset = DatasetReference.from_string(
+                dataset, default_project=self.project
+            )
+
+        if not isinstance(dataset, (Dataset, DatasetReference)):
+            if isinstance(dataset, DatasetListItem):
+                dataset = dataset.reference
+            else:
+                raise TypeError(
+                    "dataset must be a Dataset, DatasetReference, DatasetListItem,"
+                    " or string"
+                )
+        return dataset
+
     def create_dataset(
         self, dataset, exists_ok=False, retry=DEFAULT_RETRY, timeout=None
     ):
@@ -461,6 +477,7 @@ def create_dataset(
             dataset (Union[ \
                 google.cloud.bigquery.dataset.Dataset, \
                 google.cloud.bigquery.dataset.DatasetReference, \
+                google.cloud.bigquery.dataset.DatasetListItem, \
                 str, \
             ]):
                 A :class:`~google.cloud.bigquery.dataset.Dataset` to create.
@@ -491,10 +508,7 @@ def create_dataset(
             >>> dataset = client.create_dataset(dataset)
 
         """
-        if isinstance(dataset, str):
-            dataset = DatasetReference.from_string(
-                dataset, default_project=self.project
-            )
+        dataset = self._dataset_from_arg(dataset)
         if isinstance(dataset, DatasetReference):
             dataset = Dataset(dataset)
 
@@ -1133,6 +1147,7 @@ def list_models(
             dataset (Union[ \
                 google.cloud.bigquery.dataset.Dataset, \
                 google.cloud.bigquery.dataset.DatasetReference, \
+                google.cloud.bigquery.dataset.DatasetListItem, \
                 str, \
             ]):
                 A reference to the dataset whose models to list from the
@@ -1160,13 +1175,7 @@ def list_models(
                 :class:`~google.cloud.bigquery.model.Model` contained
                 within the requested dataset.
         """
-        if isinstance(dataset, str):
-            dataset = DatasetReference.from_string(
-                dataset, default_project=self.project
-            )
-
-        if not isinstance(dataset, (Dataset, DatasetReference)):
-            raise TypeError("dataset must be a Dataset, DatasetReference, or string")
+        dataset = self._dataset_from_arg(dataset)
 
         path = "%s/models" % dataset.path
         span_attributes = {"path": path}
@@ -1210,6 +1219,7 @@ def list_routines(
             dataset (Union[ \
                 google.cloud.bigquery.dataset.Dataset, \
                 google.cloud.bigquery.dataset.DatasetReference, \
+                google.cloud.bigquery.dataset.DatasetListItem, \
                 str, \
             ]):
                 A reference to the dataset whose routines to list from the
@@ -1237,14 +1247,7 @@ def list_routines(
                 :class:`~google.cloud.bigquery.routine.Routine`s contained
                 within the requested dataset, limited by ``max_results``.
         """
-        if isinstance(dataset, str):
-            dataset = DatasetReference.from_string(
-                dataset, default_project=self.project
-            )
-
-        if not isinstance(dataset, (Dataset, DatasetReference)):
-            raise TypeError("dataset must be a Dataset, DatasetReference, or string")
-
+        dataset = self._dataset_from_arg(dataset)
         path = "{}/routines".format(dataset.path)
 
         span_attributes = {"path": path}
@@ -1288,6 +1291,7 @@ def list_tables(
             dataset (Union[ \
                 google.cloud.bigquery.dataset.Dataset, \
                 google.cloud.bigquery.dataset.DatasetReference, \
+                google.cloud.bigquery.dataset.DatasetListItem, \
                 str, \
             ]):
                 A reference to the dataset whose tables to list from the
@@ -1315,14 +1319,7 @@ def list_tables(
                 :class:`~google.cloud.bigquery.table.TableListItem` contained
                 within the requested dataset.
         """
-        if isinstance(dataset, str):
-            dataset = DatasetReference.from_string(
-                dataset, default_project=self.project
-            )
-
-        if not isinstance(dataset, (Dataset, DatasetReference)):
-            raise TypeError("dataset must be a Dataset, DatasetReference, or string")
-
+        dataset = self._dataset_from_arg(dataset)
         path = "%s/tables" % dataset.path
         span_attributes = {"path": path}
 
@@ -1365,6 +1362,7 @@ def delete_dataset(
             dataset (Union[ \
                 google.cloud.bigquery.dataset.Dataset, \
                 google.cloud.bigquery.dataset.DatasetReference, \
+                google.cloud.bigquery.dataset.DatasetListItem, \
                 str, \
             ]):
                 A reference to the dataset to delete. If a string is passed
@@ -1384,14 +1382,7 @@ def delete_dataset(
                 Defaults to ``False``. If ``True``, ignore "not found" errors
                 when deleting the dataset.
         """
-        if isinstance(dataset, str):
-            dataset = DatasetReference.from_string(
-                dataset, default_project=self.project
-            )
-
-        if not isinstance(dataset, (Dataset, DatasetReference)):
-            raise TypeError("dataset must be a Dataset or a DatasetReference")
-
+        dataset = self._dataset_from_arg(dataset)
         params = {}
         path = dataset.path
         if delete_contents:


Test patch:
diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/conftest.py
@@ -0,0 +1,23 @@
+import pytest
+
+from .helpers import make_client
+
+
+@pytest.fixture
+def client():
+    yield make_client()
+
+
+@pytest.fixture
+def PROJECT():
+    yield "PROJECT"
+
+
+@pytest.fixture
+def DS_ID():
+    yield "DATASET_ID"
+
+
+@pytest.fixture
+def LOCATION():
+    yield "us-central"
diff --git a/tests/unit/helpers.py b/tests/unit/helpers.py
--- a/tests/unit/helpers.py
+++ b/tests/unit/helpers.py
@@ -12,6 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import google.cloud.bigquery.client
+import google.cloud.bigquery.dataset
+import mock
+import pytest
+
 
 def make_connection(*responses):
     import google.cloud.bigquery._http
@@ -31,3 +36,47 @@ def _to_pyarrow(value):
     import pyarrow
 
     return pyarrow.array([value])[0]
+
+
+def make_client(project="PROJECT", **kw):
+    credentials = mock.Mock(spec=google.auth.credentials.Credentials)
+    return google.cloud.bigquery.client.Client(project, credentials, **kw)
+
+
+def make_dataset_reference_string(project, ds_id):
+    return f"{project}.{ds_id}"
+
+
+def make_dataset(project, ds_id):
+    return google.cloud.bigquery.dataset.Dataset(
+        google.cloud.bigquery.dataset.DatasetReference(project, ds_id)
+    )
+
+
+def make_dataset_list_item(project, ds_id):
+    return google.cloud.bigquery.dataset.DatasetListItem(
+        dict(datasetReference=dict(projectId=project, datasetId=ds_id))
+    )
+
+
+def identity(x):
+    return x
+
+
+def get_reference(x):
+    return x.reference
+
+
+dataset_like = [
+    (google.cloud.bigquery.dataset.DatasetReference, identity),
+    (make_dataset, identity),
+    (make_dataset_list_item, get_reference),
+    (
+        make_dataset_reference_string,
+        google.cloud.bigquery.dataset.DatasetReference.from_string,
+    ),
+]
+
+dataset_polymorphic = pytest.mark.parametrize(
+    "make_dataset,get_reference", dataset_like
+)
diff --git a/tests/unit/test_client.py b/tests/unit/test_client.py
--- a/tests/unit/test_client.py
+++ b/tests/unit/test_client.py
@@ -856,2505 +856,1643 @@ def fail_bqstorage_import(name, globals, locals, fromlist, level):
         ]
         assert matching_warnings, "Missing dependency warning not raised."
 
-    def test_create_dataset_minimal(self):
-        from google.cloud.bigquery.dataset import Dataset
+    def test_create_routine_w_minimal_resource(self):
+        from google.cloud.bigquery.routine import Routine
+        from google.cloud.bigquery.routine import RoutineReference
 
-        PATH = "projects/%s/datasets" % self.PROJECT
-        RESOURCE = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-        }
         creds = _make_credentials()
+        path = "/projects/test-routine-project/datasets/test_routines/routines"
+        resource = {
+            "routineReference": {
+                "projectId": "test-routine-project",
+                "datasetId": "test_routines",
+                "routineId": "minimal_routine",
+            }
+        }
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(RESOURCE)
-
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        before = Dataset(ds_ref)
+        conn = client._connection = make_connection(resource)
+        full_routine_id = "test-routine-project.test_routines.minimal_routine"
+        routine = Routine(full_routine_id)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            after = client.create_dataset(before, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
+            actual_routine = client.create_routine(routine, timeout=7.5)
 
-        self.assertEqual(after.dataset_id, self.DS_ID)
-        self.assertEqual(after.project, self.PROJECT)
-        self.assertEqual(after.etag, RESOURCE["etag"])
-        self.assertEqual(after.full_dataset_id, RESOURCE["id"])
+        final_attributes.assert_called_once_with({"path": path}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % PATH,
-            data={
-                "datasetReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                },
-                "labels": {},
-            },
-            timeout=7.5,
+            method="POST", path=path, data=resource, timeout=7.5,
+        )
+        self.assertEqual(
+            actual_routine.reference, RoutineReference.from_string(full_routine_id)
         )
 
-    def test_create_dataset_w_attrs(self):
-        from google.cloud.bigquery.dataset import Dataset, AccessEntry
+    def test_create_routine_w_conflict(self):
+        from google.cloud.bigquery.routine import Routine
 
-        PATH = "projects/%s/datasets" % self.PROJECT
-        DESCRIPTION = "DESC"
-        FRIENDLY_NAME = "FN"
-        LOCATION = "US"
-        USER_EMAIL = "phred@example.com"
-        LABELS = {"color": "red"}
-        VIEW = {
-            "projectId": "my-proj",
-            "datasetId": "starry-skies",
-            "tableId": "northern-hemisphere",
+        creds = _make_credentials()
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        conn = client._connection = make_connection(
+            google.api_core.exceptions.AlreadyExists("routine already exists")
+        )
+        path = "/projects/test-routine-project/datasets/test_routines/routines"
+        full_routine_id = "test-routine-project.test_routines.minimal_routine"
+        routine = Routine(full_routine_id)
+
+        with pytest.raises(google.api_core.exceptions.AlreadyExists):
+            with mock.patch(
+                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+            ) as final_attributes:
+                client.create_routine(routine)
+
+        final_attributes.assert_called_once_with({"path": path}, client, None)
+
+        resource = {
+            "routineReference": {
+                "projectId": "test-routine-project",
+                "datasetId": "test_routines",
+                "routineId": "minimal_routine",
+            }
         }
-        RESOURCE = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "description": DESCRIPTION,
-            "friendlyName": FRIENDLY_NAME,
-            "location": LOCATION,
-            "defaultTableExpirationMs": "3600",
-            "labels": LABELS,
-            "access": [{"role": "OWNER", "userByEmail": USER_EMAIL}, {"view": VIEW}],
+        conn.api_request.assert_called_once_with(
+            method="POST", path=path, data=resource, timeout=None,
+        )
+
+    @unittest.skipIf(opentelemetry is None, "Requires `opentelemetry`")
+    def test_span_status_is_set(self):
+        from google.cloud.bigquery.routine import Routine
+
+        tracer_provider = TracerProvider()
+        memory_exporter = InMemorySpanExporter()
+        span_processor = SimpleExportSpanProcessor(memory_exporter)
+        tracer_provider.add_span_processor(span_processor)
+        trace.set_tracer_provider(tracer_provider)
+
+        creds = _make_credentials()
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        conn = client._connection = make_connection(
+            google.api_core.exceptions.AlreadyExists("routine already exists")
+        )
+        path = "/projects/test-routine-project/datasets/test_routines/routines"
+        full_routine_id = "test-routine-project.test_routines.minimal_routine"
+        routine = Routine(full_routine_id)
+
+        with pytest.raises(google.api_core.exceptions.AlreadyExists):
+            client.create_routine(routine)
+
+        span_list = memory_exporter.get_finished_spans()
+        self.assertTrue(span_list[0].status is not None)
+
+        resource = {
+            "routineReference": {
+                "projectId": "test-routine-project",
+                "datasetId": "test_routines",
+                "routineId": "minimal_routine",
+            }
         }
+        conn.api_request.assert_called_once_with(
+            method="POST", path=path, data=resource, timeout=None,
+        )
+
+    def test_create_routine_w_conflict_exists_ok(self):
+        from google.cloud.bigquery.routine import Routine
+
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(RESOURCE)
-        entries = [
-            AccessEntry("OWNER", "userByEmail", USER_EMAIL),
-            AccessEntry(None, "view", VIEW),
-        ]
+        resource = {
+            "routineReference": {
+                "projectId": "test-routine-project",
+                "datasetId": "test_routines",
+                "routineId": "minimal_routine",
+            }
+        }
+        path = "/projects/test-routine-project/datasets/test_routines/routines"
 
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        before = Dataset(ds_ref)
-        before.access_entries = entries
-        before.description = DESCRIPTION
-        before.friendly_name = FRIENDLY_NAME
-        before.default_table_expiration_ms = 3600
-        before.location = LOCATION
-        before.labels = LABELS
+        conn = client._connection = make_connection(
+            google.api_core.exceptions.AlreadyExists("routine already exists"), resource
+        )
+        full_routine_id = "test-routine-project.test_routines.minimal_routine"
+        routine = Routine(full_routine_id)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            after = client.create_dataset(before)
+            actual_routine = client.create_routine(routine, exists_ok=True)
 
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
+        final_attributes.assert_called_with(
+            {"path": "%s/minimal_routine" % path}, client, None
+        )
+
+        self.assertEqual(actual_routine.project, "test-routine-project")
+        self.assertEqual(actual_routine.dataset_id, "test_routines")
+        self.assertEqual(actual_routine.routine_id, "minimal_routine")
+        conn.api_request.assert_has_calls(
+            [
+                mock.call(method="POST", path=path, data=resource, timeout=None,),
+                mock.call(
+                    method="GET",
+                    path="/projects/test-routine-project/datasets/test_routines/routines/minimal_routine",
+                    timeout=None,
+                ),
+            ]
+        )
+
+    def test_create_table_w_day_partition(self):
+        from google.cloud.bigquery.table import Table
+        from google.cloud.bigquery.table import TimePartitioning
+
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
+        creds = _make_credentials()
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF)
+        table.time_partitioning = TimePartitioning()
+        with mock.patch(
+            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+        ) as final_attributes:
+            got = client.create_table(table, timeout=7.5)
 
-        self.assertEqual(after.dataset_id, self.DS_ID)
-        self.assertEqual(after.project, self.PROJECT)
-        self.assertEqual(after.etag, RESOURCE["etag"])
-        self.assertEqual(after.full_dataset_id, RESOURCE["id"])
-        self.assertEqual(after.description, DESCRIPTION)
-        self.assertEqual(after.friendly_name, FRIENDLY_NAME)
-        self.assertEqual(after.location, LOCATION)
-        self.assertEqual(after.default_table_expiration_ms, 3600)
-        self.assertEqual(after.labels, LABELS)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path="/%s" % PATH,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
                 },
-                "description": DESCRIPTION,
-                "friendlyName": FRIENDLY_NAME,
-                "location": LOCATION,
-                "defaultTableExpirationMs": "3600",
-                "access": [
-                    {"role": "OWNER", "userByEmail": USER_EMAIL},
-                    {"view": VIEW},
-                ],
-                "labels": LABELS,
+                "timePartitioning": {"type": "DAY"},
+                "labels": {},
             },
-            timeout=None,
+            timeout=7.5,
         )
+        self.assertEqual(table.time_partitioning.type_, "DAY")
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-    def test_create_dataset_w_custom_property(self):
+    def test_create_table_w_custom_property(self):
         # The library should handle sending properties to the API that are not
         # yet part of the library
-        from google.cloud.bigquery.dataset import Dataset
+        from google.cloud.bigquery.table import Table
 
-        path = "/projects/%s/datasets" % self.PROJECT
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "newAlphaProperty": "unreleased property",
-        }
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        resource["newAlphaProperty"] = "unreleased property"
         conn = client._connection = make_connection(resource)
-
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        before = Dataset(ds_ref)
-        before._properties["newAlphaProperty"] = "unreleased property"
+        table = Table(self.TABLE_REF)
+        table._properties["newAlphaProperty"] = "unreleased property"
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            after = client.create_dataset(before)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            got = client.create_table(table)
 
-        self.assertEqual(after.dataset_id, self.DS_ID)
-        self.assertEqual(after.project, self.PROJECT)
-        self.assertEqual(after._properties["newAlphaProperty"], "unreleased property")
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path=path,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
                 },
                 "newAlphaProperty": "unreleased property",
                 "labels": {},
             },
             timeout=None,
         )
+        self.assertEqual(got._properties["newAlphaProperty"], "unreleased property")
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-    def test_create_dataset_w_client_location_wo_dataset_location(self):
-        from google.cloud.bigquery.dataset import Dataset
+    def test_create_table_w_encryption_configuration(self):
+        from google.cloud.bigquery.encryption_configuration import (
+            EncryptionConfiguration,
+        )
+        from google.cloud.bigquery.table import Table
 
-        PATH = "projects/%s/datasets" % self.PROJECT
-        RESOURCE = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "location": self.LOCATION,
-        }
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF)
+        table.encryption_configuration = EncryptionConfiguration(
+            kms_key_name=self.KMS_KEY_NAME
         )
-        conn = client._connection = make_connection(RESOURCE)
-
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        before = Dataset(ds_ref)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            after = client.create_dataset(before)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
+            got = client.create_table(table)
 
-        self.assertEqual(after.dataset_id, self.DS_ID)
-        self.assertEqual(after.project, self.PROJECT)
-        self.assertEqual(after.etag, RESOURCE["etag"])
-        self.assertEqual(after.full_dataset_id, RESOURCE["id"])
-        self.assertEqual(after.location, self.LOCATION)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path="/%s" % PATH,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
                 },
                 "labels": {},
-                "location": self.LOCATION,
+                "encryptionConfiguration": {"kmsKeyName": self.KMS_KEY_NAME},
             },
             timeout=None,
         )
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-    def test_create_dataset_w_client_location_w_dataset_location(self):
-        from google.cloud.bigquery.dataset import Dataset
+    def test_create_table_w_day_partition_and_expire(self):
+        from google.cloud.bigquery.table import Table
+        from google.cloud.bigquery.table import TimePartitioning
 
-        PATH = "projects/%s/datasets" % self.PROJECT
-        OTHER_LOCATION = "EU"
-        RESOURCE = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "location": OTHER_LOCATION,
-        }
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
-        conn = client._connection = make_connection(RESOURCE)
-
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        before = Dataset(ds_ref)
-        before.location = OTHER_LOCATION
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF)
+        table.time_partitioning = TimePartitioning(expiration_ms=100)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            after = client.create_dataset(before)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
+            got = client.create_table(table)
 
-        self.assertEqual(after.dataset_id, self.DS_ID)
-        self.assertEqual(after.project, self.PROJECT)
-        self.assertEqual(after.etag, RESOURCE["etag"])
-        self.assertEqual(after.full_dataset_id, RESOURCE["id"])
-        self.assertEqual(after.location, OTHER_LOCATION)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path="/%s" % PATH,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
                 },
+                "timePartitioning": {"type": "DAY", "expirationMs": "100"},
                 "labels": {},
-                "location": OTHER_LOCATION,
             },
             timeout=None,
         )
+        self.assertEqual(table.time_partitioning.type_, "DAY")
+        self.assertEqual(table.time_partitioning.expiration_ms, 100)
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-    def test_create_dataset_w_reference(self):
-        path = "/projects/%s/datasets" % self.PROJECT
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "location": self.LOCATION,
-        }
+    def test_create_table_w_schema_and_query(self):
+        from google.cloud.bigquery.schema import SchemaField
+        from google.cloud.bigquery.table import Table
+
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
+        query = "SELECT * from %s:%s" % (self.DS_ID, self.TABLE_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        resource.update(
+            {
+                "schema": {
+                    "fields": [
+                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
+                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
+                    ]
+                },
+                "view": {"query": query},
+            }
         )
+        schema = [
+            SchemaField("full_name", "STRING", mode="REQUIRED"),
+            SchemaField("age", "INTEGER", mode="REQUIRED"),
+        ]
         conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF, schema=schema)
+        table.view_query = query
+
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            dataset = client.create_dataset(DatasetReference(self.PROJECT, self.DS_ID))
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            got = client.create_table(table)
 
-        self.assertEqual(dataset.dataset_id, self.DS_ID)
-        self.assertEqual(dataset.project, self.PROJECT)
-        self.assertEqual(dataset.etag, resource["etag"])
-        self.assertEqual(dataset.full_dataset_id, resource["id"])
-        self.assertEqual(dataset.location, self.LOCATION)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path=path,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
+                },
+                "schema": {
+                    "fields": [
+                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
+                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
+                    ]
                 },
+                "view": {"query": query, "useLegacySql": False},
                 "labels": {},
-                "location": self.LOCATION,
             },
             timeout=None,
         )
+        self.assertEqual(got.table_id, self.TABLE_ID)
+        self.assertEqual(got.project, self.PROJECT)
+        self.assertEqual(got.dataset_id, self.DS_ID)
+        self.assertEqual(got.schema, schema)
+        self.assertEqual(got.view_query, query)
 
-    def test_create_dataset_w_fully_qualified_string(self):
-        path = "/projects/%s/datasets" % self.PROJECT
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "location": self.LOCATION,
-        }
+    def test_create_table_w_external(self):
+        from google.cloud.bigquery.external_config import ExternalConfig
+        from google.cloud.bigquery.job import SourceFormat
+        from google.cloud.bigquery.table import Table
+
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        resource.update(
+            {
+                "externalDataConfiguration": {
+                    "sourceFormat": SourceFormat.CSV,
+                    "autodetect": True,
+                }
+            }
         )
         conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF)
+        ec = ExternalConfig("CSV")
+        ec.autodetect = True
+        table.external_data_configuration = ec
+
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            dataset = client.create_dataset("{}.{}".format(self.PROJECT, self.DS_ID))
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            got = client.create_table(table)
 
-        self.assertEqual(dataset.dataset_id, self.DS_ID)
-        self.assertEqual(dataset.project, self.PROJECT)
-        self.assertEqual(dataset.etag, resource["etag"])
-        self.assertEqual(dataset.full_dataset_id, resource["id"])
-        self.assertEqual(dataset.location, self.LOCATION)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path=path,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
+                },
+                "externalDataConfiguration": {
+                    "sourceFormat": SourceFormat.CSV,
+                    "autodetect": True,
                 },
                 "labels": {},
-                "location": self.LOCATION,
             },
             timeout=None,
         )
+        self.assertEqual(got.table_id, self.TABLE_ID)
+        self.assertEqual(got.project, self.PROJECT)
+        self.assertEqual(got.dataset_id, self.DS_ID)
+        self.assertEqual(
+            got.external_data_configuration.source_format, SourceFormat.CSV
+        )
+        self.assertEqual(got.external_data_configuration.autodetect, True)
 
-    def test_create_dataset_w_string(self):
-        path = "/projects/%s/datasets" % self.PROJECT
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "%s:%s" % (self.PROJECT, self.DS_ID),
-            "location": self.LOCATION,
-        }
+    def test_create_table_w_reference(self):
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
         conn = client._connection = make_connection(resource)
+
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            dataset = client.create_dataset(self.DS_ID)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            got = client.create_table(self.TABLE_REF)
 
-        self.assertEqual(dataset.dataset_id, self.DS_ID)
-        self.assertEqual(dataset.project, self.PROJECT)
-        self.assertEqual(dataset.etag, resource["etag"])
-        self.assertEqual(dataset.full_dataset_id, resource["id"])
-        self.assertEqual(dataset.location, self.LOCATION)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
+            client,
+            None,
+        )
 
         conn.api_request.assert_called_once_with(
             method="POST",
-            path=path,
+            path="/%s" % path,
             data={
-                "datasetReference": {
+                "tableReference": {
                     "projectId": self.PROJECT,
                     "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
                 },
                 "labels": {},
-                "location": self.LOCATION,
             },
             timeout=None,
         )
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-    def test_create_dataset_alreadyexists_w_exists_ok_false(self):
-        creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
-        client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("dataset already exists")
-        )
-
-        with pytest.raises(google.api_core.exceptions.AlreadyExists):
-            client.create_dataset(self.DS_ID)
-
-    def test_create_dataset_alreadyexists_w_exists_ok_true(self):
-        post_path = "/projects/{}/datasets".format(self.PROJECT)
-        get_path = "/projects/{}/datasets/{}".format(self.PROJECT, self.DS_ID)
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "id": "{}:{}".format(self.PROJECT, self.DS_ID),
-            "location": self.LOCATION,
-        }
+    def test_create_table_w_fully_qualified_string(self):
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("dataset already exists"), resource
-        )
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
+        conn = client._connection = make_connection(resource)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            dataset = client.create_dataset(self.DS_ID, exists_ok=True)
-
-        final_attributes.assert_called_with({"path": get_path}, client, None)
-
-        self.assertEqual(dataset.dataset_id, self.DS_ID)
-        self.assertEqual(dataset.project, self.PROJECT)
-        self.assertEqual(dataset.etag, resource["etag"])
-        self.assertEqual(dataset.full_dataset_id, resource["id"])
-        self.assertEqual(dataset.location, self.LOCATION)
+            got = client.create_table(
+                "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.TABLE_ID)
+            )
 
-        conn.api_request.assert_has_calls(
-            [
-                mock.call(
-                    method="POST",
-                    path=post_path,
-                    data={
-                        "datasetReference": {
-                            "projectId": self.PROJECT,
-                            "datasetId": self.DS_ID,
-                        },
-                        "labels": {},
-                        "location": self.LOCATION,
-                    },
-                    timeout=None,
-                ),
-                mock.call(method="GET", path=get_path, timeout=None),
-            ]
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
+            client,
+            None,
         )
 
-    def test_create_routine_w_minimal_resource(self):
-        from google.cloud.bigquery.routine import Routine
-        from google.cloud.bigquery.routine import RoutineReference
+        conn.api_request.assert_called_once_with(
+            method="POST",
+            path="/%s" % path,
+            data={
+                "tableReference": {
+                    "projectId": self.PROJECT,
+                    "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
+                },
+                "labels": {},
+            },
+            timeout=None,
+        )
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
+    def test_create_table_w_string(self):
+        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        path = "/projects/test-routine-project/datasets/test_routines/routines"
-        resource = {
-            "routineReference": {
-                "projectId": "test-routine-project",
-                "datasetId": "test_routines",
-                "routineId": "minimal_routine",
-            }
-        }
         client = self._make_one(project=self.PROJECT, credentials=creds)
+        resource = self._make_table_resource()
         conn = client._connection = make_connection(resource)
-        full_routine_id = "test-routine-project.test_routines.minimal_routine"
-        routine = Routine(full_routine_id)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            actual_routine = client.create_routine(routine, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            got = client.create_table("{}.{}".format(self.DS_ID, self.TABLE_ID))
 
-        conn.api_request.assert_called_once_with(
-            method="POST", path=path, data=resource, timeout=7.5,
-        )
-        self.assertEqual(
-            actual_routine.reference, RoutineReference.from_string(full_routine_id)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
+            client,
+            None,
         )
 
-    def test_create_routine_w_conflict(self):
-        from google.cloud.bigquery.routine import Routine
+        conn.api_request.assert_called_once_with(
+            method="POST",
+            path="/%s" % path,
+            data={
+                "tableReference": {
+                    "projectId": self.PROJECT,
+                    "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
+                },
+                "labels": {},
+            },
+            timeout=None,
+        )
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
+    def test_create_table_alreadyexists_w_exists_ok_false(self):
+        post_path = "/projects/{}/datasets/{}/tables".format(self.PROJECT, self.DS_ID)
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
+        client = self._make_one(
+            project=self.PROJECT, credentials=creds, location=self.LOCATION
+        )
         conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("routine already exists")
+            google.api_core.exceptions.AlreadyExists("table already exists")
         )
-        path = "/projects/test-routine-project/datasets/test_routines/routines"
-        full_routine_id = "test-routine-project.test_routines.minimal_routine"
-        routine = Routine(full_routine_id)
 
         with pytest.raises(google.api_core.exceptions.AlreadyExists):
             with mock.patch(
                 "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
             ) as final_attributes:
-                client.create_routine(routine)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
-
-        resource = {
-            "routineReference": {
-                "projectId": "test-routine-project",
-                "datasetId": "test_routines",
-                "routineId": "minimal_routine",
-            }
-        }
-        conn.api_request.assert_called_once_with(
-            method="POST", path=path, data=resource, timeout=None,
-        )
-
-    @unittest.skipIf(opentelemetry is None, "Requires `opentelemetry`")
-    def test_span_status_is_set(self):
-        from google.cloud.bigquery.routine import Routine
-
-        tracer_provider = TracerProvider()
-        memory_exporter = InMemorySpanExporter()
-        span_processor = SimpleExportSpanProcessor(memory_exporter)
-        tracer_provider.add_span_processor(span_processor)
-        trace.set_tracer_provider(tracer_provider)
+                client.create_table("{}.{}".format(self.DS_ID, self.TABLE_ID))
 
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("routine already exists")
+        final_attributes.assert_called_with(
+            {"path": post_path, "dataset_id": self.TABLE_REF.dataset_id}, client, None,
         )
-        path = "/projects/test-routine-project/datasets/test_routines/routines"
-        full_routine_id = "test-routine-project.test_routines.minimal_routine"
-        routine = Routine(full_routine_id)
-
-        with pytest.raises(google.api_core.exceptions.AlreadyExists):
-            client.create_routine(routine)
-
-        span_list = memory_exporter.get_finished_spans()
-        self.assertTrue(span_list[0].status is not None)
 
-        resource = {
-            "routineReference": {
-                "projectId": "test-routine-project",
-                "datasetId": "test_routines",
-                "routineId": "minimal_routine",
-            }
-        }
         conn.api_request.assert_called_once_with(
-            method="POST", path=path, data=resource, timeout=None,
+            method="POST",
+            path=post_path,
+            data={
+                "tableReference": {
+                    "projectId": self.PROJECT,
+                    "datasetId": self.DS_ID,
+                    "tableId": self.TABLE_ID,
+                },
+                "labels": {},
+            },
+            timeout=None,
         )
 
-    def test_create_routine_w_conflict_exists_ok(self):
-        from google.cloud.bigquery.routine import Routine
-
+    def test_create_table_alreadyexists_w_exists_ok_true(self):
+        post_path = "/projects/{}/datasets/{}/tables".format(self.PROJECT, self.DS_ID)
+        get_path = "/projects/{}/datasets/{}/tables/{}".format(
+            self.PROJECT, self.DS_ID, self.TABLE_ID
+        )
+        resource = self._make_table_resource()
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = {
-            "routineReference": {
-                "projectId": "test-routine-project",
-                "datasetId": "test_routines",
-                "routineId": "minimal_routine",
-            }
-        }
-        path = "/projects/test-routine-project/datasets/test_routines/routines"
-
+        client = self._make_one(
+            project=self.PROJECT, credentials=creds, location=self.LOCATION
+        )
         conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("routine already exists"), resource
+            google.api_core.exceptions.AlreadyExists("table already exists"), resource
         )
-        full_routine_id = "test-routine-project.test_routines.minimal_routine"
-        routine = Routine(full_routine_id)
+
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            actual_routine = client.create_routine(routine, exists_ok=True)
+            got = client.create_table(
+                "{}.{}".format(self.DS_ID, self.TABLE_ID), exists_ok=True
+            )
 
-        final_attributes.assert_called_with(
-            {"path": "%s/minimal_routine" % path}, client, None
-        )
+        final_attributes.assert_called_with({"path": get_path}, client, None)
+
+        self.assertEqual(got.project, self.PROJECT)
+        self.assertEqual(got.dataset_id, self.DS_ID)
+        self.assertEqual(got.table_id, self.TABLE_ID)
 
-        self.assertEqual(actual_routine.project, "test-routine-project")
-        self.assertEqual(actual_routine.dataset_id, "test_routines")
-        self.assertEqual(actual_routine.routine_id, "minimal_routine")
         conn.api_request.assert_has_calls(
             [
-                mock.call(method="POST", path=path, data=resource, timeout=None,),
                 mock.call(
-                    method="GET",
-                    path="/projects/test-routine-project/datasets/test_routines/routines/minimal_routine",
+                    method="POST",
+                    path=post_path,
+                    data={
+                        "tableReference": {
+                            "projectId": self.PROJECT,
+                            "datasetId": self.DS_ID,
+                            "tableId": self.TABLE_ID,
+                        },
+                        "labels": {},
+                    },
                     timeout=None,
                 ),
+                mock.call(method="GET", path=get_path, timeout=None),
             ]
         )
 
-    def test_create_table_w_day_partition(self):
-        from google.cloud.bigquery.table import Table
-        from google.cloud.bigquery.table import TimePartitioning
+    def test_close(self):
+        creds = _make_credentials()
+        http = mock.Mock()
+        http._auth_request.session = mock.Mock()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
+        client.close()
+
+        http.close.assert_called_once()
+        http._auth_request.session.close.assert_called_once()
+
+    def test_get_model(self):
+        path = "projects/%s/datasets/%s/models/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.MODEL_ID,
+        )
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        resource = {
+            "modelReference": {
+                "projectId": self.PROJECT,
+                "datasetId": self.DS_ID,
+                "modelId": self.MODEL_ID,
+            }
+        }
         conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table.time_partitioning = TimePartitioning()
+
+        model_ref = DatasetReference(self.PROJECT, self.DS_ID).model(self.MODEL_ID)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            got = client.create_table(table, timeout=7.5)
+            got = client.get_model(model_ref, timeout=7.5)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
-        )
+        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "timePartitioning": {"type": "DAY"},
-                "labels": {},
-            },
-            timeout=7.5,
+            method="GET", path="/%s" % path, timeout=7.5
         )
-        self.assertEqual(table.time_partitioning.type_, "DAY")
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-    def test_create_table_w_custom_property(self):
-        # The library should handle sending properties to the API that are not
-        # yet part of the library
-        from google.cloud.bigquery.table import Table
+        self.assertEqual(got.model_id, self.MODEL_ID)
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
+    def test_get_model_w_string(self):
+        path = "projects/%s/datasets/%s/models/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.MODEL_ID,
+        )
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        resource["newAlphaProperty"] = "unreleased property"
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        resource = {
+            "modelReference": {
+                "projectId": self.PROJECT,
+                "datasetId": self.DS_ID,
+                "modelId": self.MODEL_ID,
+            }
+        }
         conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table._properties["newAlphaProperty"] = "unreleased property"
+
+        model_id = "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.MODEL_ID)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            got = client.create_table(table)
+            got = client.get_model(model_id)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
-        )
+        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "newAlphaProperty": "unreleased property",
-                "labels": {},
-            },
-            timeout=None,
+            method="GET", path="/%s" % path, timeout=None
         )
-        self.assertEqual(got._properties["newAlphaProperty"], "unreleased property")
-        self.assertEqual(got.table_id, self.TABLE_ID)
+        self.assertEqual(got.model_id, self.MODEL_ID)
 
-    def test_create_table_w_encryption_configuration(self):
-        from google.cloud.bigquery.encryption_configuration import (
-            EncryptionConfiguration,
-        )
-        from google.cloud.bigquery.table import Table
+    def test_get_routine(self):
+        from google.cloud.bigquery.routine import Routine
+        from google.cloud.bigquery.routine import RoutineReference
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table.encryption_configuration = EncryptionConfiguration(
-            kms_key_name=self.KMS_KEY_NAME
-        )
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(table)
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
+        full_routine_id = "test-routine-project.test_routines.minimal_routine"
+        routines = [
+            full_routine_id,
+            Routine(full_routine_id),
+            RoutineReference.from_string(full_routine_id),
+        ]
+        for routine in routines:
+            creds = _make_credentials()
+            resource = {
+                "etag": "im-an-etag",
+                "routineReference": {
+                    "projectId": "test-routine-project",
+                    "datasetId": "test_routines",
+                    "routineId": "minimal_routine",
                 },
-                "labels": {},
-                "encryptionConfiguration": {"kmsKeyName": self.KMS_KEY_NAME},
-            },
-            timeout=None,
-        )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-    def test_create_table_w_day_partition_and_expire(self):
-        from google.cloud.bigquery.table import Table
-        from google.cloud.bigquery.table import TimePartitioning
+                "routineType": "SCALAR_FUNCTION",
+            }
+            path = "/projects/test-routine-project/datasets/test_routines/routines/minimal_routine"
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table.time_partitioning = TimePartitioning(expiration_ms=100)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(table)
+            client = self._make_one(project=self.PROJECT, credentials=creds)
+            conn = client._connection = make_connection(resource)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
-        )
+            with mock.patch(
+                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+            ) as final_attributes:
+                actual_routine = client.get_routine(routine, timeout=7.5)
 
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "timePartitioning": {"type": "DAY", "expirationMs": "100"},
-                "labels": {},
-            },
-            timeout=None,
-        )
-        self.assertEqual(table.time_partitioning.type_, "DAY")
-        self.assertEqual(table.time_partitioning.expiration_ms, 100)
-        self.assertEqual(got.table_id, self.TABLE_ID)
+            final_attributes.assert_called_once_with({"path": path}, client, None)
 
-    def test_create_table_w_schema_and_query(self):
-        from google.cloud.bigquery.schema import SchemaField
-        from google.cloud.bigquery.table import Table
+            conn.api_request.assert_called_once_with(
+                method="GET", path=path, timeout=7.5,
+            )
+            self.assertEqual(
+                actual_routine.reference,
+                RoutineReference.from_string(full_routine_id),
+                msg="routine={}".format(repr(routine)),
+            )
+            self.assertEqual(
+                actual_routine.etag,
+                "im-an-etag",
+                msg="routine={}".format(repr(routine)),
+            )
+            self.assertEqual(
+                actual_routine.type_,
+                "SCALAR_FUNCTION",
+                msg="routine={}".format(repr(routine)),
+            )
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        query = "SELECT * from %s:%s" % (self.DS_ID, self.TABLE_ID)
+    def test_get_table(self):
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
         resource = self._make_table_resource()
-        resource.update(
-            {
-                "schema": {
-                    "fields": [
-                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
-                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
-                    ]
-                },
-                "view": {"query": query},
-            }
-        )
-        schema = [
-            SchemaField("full_name", "STRING", mode="REQUIRED"),
-            SchemaField("age", "INTEGER", mode="REQUIRED"),
-        ]
         conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF, schema=schema)
-        table.view_query = query
-
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            got = client.create_table(table)
+            table = client.get_table(self.TABLE_REF, timeout=7.5)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
-        )
+        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "schema": {
-                    "fields": [
-                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
-                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
-                    ]
-                },
-                "view": {"query": query, "useLegacySql": False},
-                "labels": {},
-            },
-            timeout=None,
+            method="GET", path="/%s" % path, timeout=7.5
         )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-        self.assertEqual(got.project, self.PROJECT)
-        self.assertEqual(got.dataset_id, self.DS_ID)
-        self.assertEqual(got.schema, schema)
-        self.assertEqual(got.view_query, query)
-
-    def test_create_table_w_external(self):
-        from google.cloud.bigquery.external_config import ExternalConfig
-        from google.cloud.bigquery.job import SourceFormat
-        from google.cloud.bigquery.table import Table
+        self.assertEqual(table.table_id, self.TABLE_ID)
 
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
+    def test_get_table_sets_user_agent(self):
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        resource.update(
-            {
-                "externalDataConfiguration": {
-                    "sourceFormat": SourceFormat.CSV,
-                    "autodetect": True,
-                }
-            }
+        http = mock.create_autospec(requests.Session)
+        mock_response = http.request(
+            url=mock.ANY, method=mock.ANY, headers=mock.ANY, data=mock.ANY
         )
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        ec = ExternalConfig("CSV")
-        ec.autodetect = True
-        table.external_data_configuration = ec
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(table)
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": table.dataset_id}, client, None
+        http.reset_mock()
+        http.is_mtls = False
+        mock_response.status_code = 200
+        mock_response.json.return_value = self._make_table_resource()
+        user_agent_override = client_info.ClientInfo(user_agent="my-application/1.2.3")
+        client = self._make_one(
+            project=self.PROJECT,
+            credentials=creds,
+            client_info=user_agent_override,
+            _http=http,
         )
 
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "externalDataConfiguration": {
-                    "sourceFormat": SourceFormat.CSV,
-                    "autodetect": True,
-                },
-                "labels": {},
+        client.get_table(self.TABLE_REF)
+
+        expected_user_agent = user_agent_override.to_user_agent()
+        http.request.assert_called_once_with(
+            url=mock.ANY,
+            method="GET",
+            headers={
+                "X-Goog-API-Client": expected_user_agent,
+                "Accept-Encoding": "gzip",
+                "User-Agent": expected_user_agent,
             },
+            data=mock.ANY,
             timeout=None,
         )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-        self.assertEqual(got.project, self.PROJECT)
-        self.assertEqual(got.dataset_id, self.DS_ID)
-        self.assertEqual(
-            got.external_data_configuration.source_format, SourceFormat.CSV
-        )
-        self.assertEqual(got.external_data_configuration.autodetect, True)
-
-    def test_create_table_w_reference(self):
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
+        self.assertIn("my-application/1.2.3", expected_user_agent)
 
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(self.TABLE_REF)
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
-            client,
-            None,
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "labels": {},
-            },
-            timeout=None,
-        )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-    def test_create_table_w_fully_qualified_string(self):
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(
-                "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.TABLE_ID)
-            )
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
-            client,
-            None,
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "labels": {},
-            },
-            timeout=None,
-        )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-    def test_create_table_w_string(self):
-        path = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table("{}.{}".format(self.DS_ID, self.TABLE_ID))
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "dataset_id": self.TABLE_REF.dataset_id},
-            client,
-            None,
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path="/%s" % path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "labels": {},
-            },
-            timeout=None,
-        )
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-    def test_create_table_alreadyexists_w_exists_ok_false(self):
-        post_path = "/projects/{}/datasets/{}/tables".format(self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("table already exists")
-        )
-
-        with pytest.raises(google.api_core.exceptions.AlreadyExists):
-            with mock.patch(
-                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-            ) as final_attributes:
-                client.create_table("{}.{}".format(self.DS_ID, self.TABLE_ID))
-
-        final_attributes.assert_called_with(
-            {"path": post_path, "dataset_id": self.TABLE_REF.dataset_id}, client, None,
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="POST",
-            path=post_path,
-            data={
-                "tableReference": {
-                    "projectId": self.PROJECT,
-                    "datasetId": self.DS_ID,
-                    "tableId": self.TABLE_ID,
-                },
-                "labels": {},
-            },
-            timeout=None,
-        )
-
-    def test_create_table_alreadyexists_w_exists_ok_true(self):
-        post_path = "/projects/{}/datasets/{}/tables".format(self.PROJECT, self.DS_ID)
-        get_path = "/projects/{}/datasets/{}/tables/{}".format(
-            self.PROJECT, self.DS_ID, self.TABLE_ID
-        )
-        resource = self._make_table_resource()
-        creds = _make_credentials()
-        client = self._make_one(
-            project=self.PROJECT, credentials=creds, location=self.LOCATION
-        )
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.AlreadyExists("table already exists"), resource
-        )
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.create_table(
-                "{}.{}".format(self.DS_ID, self.TABLE_ID), exists_ok=True
-            )
-
-        final_attributes.assert_called_with({"path": get_path}, client, None)
-
-        self.assertEqual(got.project, self.PROJECT)
-        self.assertEqual(got.dataset_id, self.DS_ID)
-        self.assertEqual(got.table_id, self.TABLE_ID)
-
-        conn.api_request.assert_has_calls(
-            [
-                mock.call(
-                    method="POST",
-                    path=post_path,
-                    data={
-                        "tableReference": {
-                            "projectId": self.PROJECT,
-                            "datasetId": self.DS_ID,
-                            "tableId": self.TABLE_ID,
-                        },
-                        "labels": {},
-                    },
-                    timeout=None,
-                ),
-                mock.call(method="GET", path=get_path, timeout=None),
-            ]
-        )
-
-    def test_close(self):
-        creds = _make_credentials()
-        http = mock.Mock()
-        http._auth_request.session = mock.Mock()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        client.close()
-
-        http.close.assert_called_once()
-        http._auth_request.session.close.assert_called_once()
-
-    def test_get_model(self):
-        path = "projects/%s/datasets/%s/models/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.MODEL_ID,
-        )
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        resource = {
-            "modelReference": {
-                "projectId": self.PROJECT,
-                "datasetId": self.DS_ID,
-                "modelId": self.MODEL_ID,
-            }
-        }
-        conn = client._connection = make_connection(resource)
-
-        model_ref = DatasetReference(self.PROJECT, self.DS_ID).model(self.MODEL_ID)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.get_model(model_ref, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="GET", path="/%s" % path, timeout=7.5
-        )
-        self.assertEqual(got.model_id, self.MODEL_ID)
-
-    def test_get_model_w_string(self):
-        path = "projects/%s/datasets/%s/models/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.MODEL_ID,
-        )
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        resource = {
-            "modelReference": {
-                "projectId": self.PROJECT,
-                "datasetId": self.DS_ID,
-                "modelId": self.MODEL_ID,
-            }
-        }
-        conn = client._connection = make_connection(resource)
-
-        model_id = "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.MODEL_ID)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            got = client.get_model(model_id)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="GET", path="/%s" % path, timeout=None
-        )
-        self.assertEqual(got.model_id, self.MODEL_ID)
-
-    def test_get_routine(self):
-        from google.cloud.bigquery.routine import Routine
-        from google.cloud.bigquery.routine import RoutineReference
-
-        full_routine_id = "test-routine-project.test_routines.minimal_routine"
-        routines = [
-            full_routine_id,
-            Routine(full_routine_id),
-            RoutineReference.from_string(full_routine_id),
-        ]
-        for routine in routines:
-            creds = _make_credentials()
-            resource = {
-                "etag": "im-an-etag",
-                "routineReference": {
-                    "projectId": "test-routine-project",
-                    "datasetId": "test_routines",
-                    "routineId": "minimal_routine",
-                },
-                "routineType": "SCALAR_FUNCTION",
-            }
-            path = "/projects/test-routine-project/datasets/test_routines/routines/minimal_routine"
-
-            client = self._make_one(project=self.PROJECT, credentials=creds)
-            conn = client._connection = make_connection(resource)
-
-            with mock.patch(
-                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-            ) as final_attributes:
-                actual_routine = client.get_routine(routine, timeout=7.5)
-
-            final_attributes.assert_called_once_with({"path": path}, client, None)
-
-            conn.api_request.assert_called_once_with(
-                method="GET", path=path, timeout=7.5,
-            )
-            self.assertEqual(
-                actual_routine.reference,
-                RoutineReference.from_string(full_routine_id),
-                msg="routine={}".format(repr(routine)),
-            )
-            self.assertEqual(
-                actual_routine.etag,
-                "im-an-etag",
-                msg="routine={}".format(repr(routine)),
-            )
-            self.assertEqual(
-                actual_routine.type_,
-                "SCALAR_FUNCTION",
-                msg="routine={}".format(repr(routine)),
-            )
-
-    def test_get_table(self):
-        path = "projects/%s/datasets/%s/tables/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        resource = self._make_table_resource()
-        conn = client._connection = make_connection(resource)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            table = client.get_table(self.TABLE_REF, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="GET", path="/%s" % path, timeout=7.5
-        )
-        self.assertEqual(table.table_id, self.TABLE_ID)
-
-    def test_get_table_sets_user_agent(self):
-        creds = _make_credentials()
-        http = mock.create_autospec(requests.Session)
-        mock_response = http.request(
-            url=mock.ANY, method=mock.ANY, headers=mock.ANY, data=mock.ANY
-        )
-        http.reset_mock()
-        http.is_mtls = False
-        mock_response.status_code = 200
-        mock_response.json.return_value = self._make_table_resource()
-        user_agent_override = client_info.ClientInfo(user_agent="my-application/1.2.3")
-        client = self._make_one(
-            project=self.PROJECT,
-            credentials=creds,
-            client_info=user_agent_override,
-            _http=http,
-        )
-
-        client.get_table(self.TABLE_REF)
-
-        expected_user_agent = user_agent_override.to_user_agent()
-        http.request.assert_called_once_with(
-            url=mock.ANY,
-            method="GET",
-            headers={
-                "X-Goog-API-Client": expected_user_agent,
-                "Accept-Encoding": "gzip",
-                "User-Agent": expected_user_agent,
-            },
-            data=mock.ANY,
-            timeout=None,
-        )
-        self.assertIn("my-application/1.2.3", expected_user_agent)
-
-    def test_get_iam_policy(self):
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_OWNER_ROLE
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_EDITOR_ROLE
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_VIEWER_ROLE
-        from google.api_core.iam import Policy
-
-        PATH = "/projects/{}/datasets/{}/tables/{}:getIamPolicy".format(
-            self.PROJECT, self.DS_ID, self.TABLE_ID,
-        )
-        BODY = {"options": {"requestedPolicyVersion": 1}}
-        ETAG = "CARDI"
-        VERSION = 1
-        OWNER1 = "user:phred@example.com"
-        OWNER2 = "group:cloud-logs@google.com"
-        EDITOR1 = "domain:google.com"
-        EDITOR2 = "user:phred@example.com"
-        VIEWER1 = "serviceAccount:1234-abcdef@service.example.com"
-        VIEWER2 = "user:phred@example.com"
-        RETURNED = {
-            "resourceId": PATH,
-            "etag": ETAG,
-            "version": VERSION,
-            "bindings": [
-                {"role": BIGQUERY_DATA_OWNER_ROLE, "members": [OWNER1, OWNER2]},
-                {"role": BIGQUERY_DATA_EDITOR_ROLE, "members": [EDITOR1, EDITOR2]},
-                {"role": BIGQUERY_DATA_VIEWER_ROLE, "members": [VIEWER1, VIEWER2]},
-            ],
-        }
-        EXPECTED = {
-            binding["role"]: set(binding["members"]) for binding in RETURNED["bindings"]
-        }
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(RETURNED)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            policy = client.get_iam_policy(self.TABLE_REF, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": PATH}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="POST", path=PATH, data=BODY, timeout=7.5
-        )
-
-        self.assertIsInstance(policy, Policy)
-        self.assertEqual(policy.etag, RETURNED["etag"])
-        self.assertEqual(policy.version, RETURNED["version"])
-        self.assertEqual(dict(policy), EXPECTED)
-
-    def test_get_iam_policy_w_invalid_table(self):
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        table_resource_string = "projects/{}/datasets/{}/tables/{}".format(
-            self.PROJECT, self.DS_ID, self.TABLE_ID,
-        )
-
-        with self.assertRaises(TypeError):
-            client.get_iam_policy(table_resource_string)
-
-    def test_get_iam_policy_w_invalid_version(self):
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        with self.assertRaises(ValueError):
-            client.get_iam_policy(self.TABLE_REF, requested_policy_version=2)
-
-    def test_set_iam_policy(self):
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_OWNER_ROLE
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_EDITOR_ROLE
-        from google.cloud.bigquery.iam import BIGQUERY_DATA_VIEWER_ROLE
-        from google.api_core.iam import Policy
-
-        PATH = "/projects/%s/datasets/%s/tables/%s:setIamPolicy" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-        ETAG = "foo"
-        VERSION = 1
-        OWNER1 = "user:phred@example.com"
-        OWNER2 = "group:cloud-logs@google.com"
-        EDITOR1 = "domain:google.com"
-        EDITOR2 = "user:phred@example.com"
-        VIEWER1 = "serviceAccount:1234-abcdef@service.example.com"
-        VIEWER2 = "user:phred@example.com"
-        BINDINGS = [
-            {"role": BIGQUERY_DATA_OWNER_ROLE, "members": [OWNER1, OWNER2]},
-            {"role": BIGQUERY_DATA_EDITOR_ROLE, "members": [EDITOR1, EDITOR2]},
-            {"role": BIGQUERY_DATA_VIEWER_ROLE, "members": [VIEWER1, VIEWER2]},
-        ]
-        MASK = "bindings,etag"
-        RETURNED = {"etag": ETAG, "version": VERSION, "bindings": BINDINGS}
-
-        policy = Policy()
-        for binding in BINDINGS:
-            policy[binding["role"]] = binding["members"]
-
-        BODY = {"policy": policy.to_api_repr(), "updateMask": MASK}
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(RETURNED)
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            returned_policy = client.set_iam_policy(
-                self.TABLE_REF, policy, updateMask=MASK, timeout=7.5
-            )
-
-        final_attributes.assert_called_once_with({"path": PATH}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="POST", path=PATH, data=BODY, timeout=7.5
-        )
-        self.assertEqual(returned_policy.etag, ETAG)
-        self.assertEqual(returned_policy.version, VERSION)
-        self.assertEqual(dict(returned_policy), dict(policy))
-
-    def test_set_iam_policy_no_mask(self):
-        from google.api_core.iam import Policy
-
-        PATH = "/projects/%s/datasets/%s/tables/%s:setIamPolicy" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-        RETURNED = {"etag": "foo", "version": 1, "bindings": []}
-
-        policy = Policy()
-        BODY = {"policy": policy.to_api_repr()}
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(RETURNED)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            client.set_iam_policy(self.TABLE_REF, policy, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": PATH}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="POST", path=PATH, data=BODY, timeout=7.5
-        )
-
-    def test_set_iam_policy_invalid_policy(self):
-        from google.api_core.iam import Policy
-
-        policy = Policy()
-        invalid_policy_repr = policy.to_api_repr()
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        with self.assertRaises(TypeError):
-            client.set_iam_policy(self.TABLE_REF, invalid_policy_repr)
-
-    def test_set_iam_policy_w_invalid_table(self):
-        from google.api_core.iam import Policy
-
-        policy = Policy()
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        table_resource_string = "projects/%s/datasets/%s/tables/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-
-        with self.assertRaises(TypeError):
-            client.set_iam_policy(table_resource_string, policy)
-
-    def test_test_iam_permissions(self):
-        PATH = "/projects/%s/datasets/%s/tables/%s:testIamPermissions" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-
-        PERMISSIONS = ["bigquery.tables.get", "bigquery.tables.update"]
-        BODY = {"permissions": PERMISSIONS}
-        RETURNED = {"permissions": PERMISSIONS}
-
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(RETURNED)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            client.test_iam_permissions(self.TABLE_REF, PERMISSIONS, timeout=7.5)
-
-        final_attributes.assert_called_once_with({"path": PATH}, client, None)
-
-        conn.api_request.assert_called_once_with(
-            method="POST", path=PATH, data=BODY, timeout=7.5
-        )
-
-    def test_test_iam_permissions_w_invalid_table(self):
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-
-        table_resource_string = "projects/%s/datasets/%s/tables/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-
-        PERMISSIONS = ["bigquery.tables.get", "bigquery.tables.update"]
-
-        with self.assertRaises(TypeError):
-            client.test_iam_permissions(table_resource_string, PERMISSIONS)
-
-    def test_update_dataset_w_invalid_field(self):
-        from google.cloud.bigquery.dataset import Dataset
-
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        with self.assertRaises(ValueError):
-            client.update_dataset(
-                Dataset("{}.{}".format(self.PROJECT, self.DS_ID)), ["foo"]
-            )
-
-    def test_update_dataset(self):
-        from google.cloud.bigquery.dataset import Dataset, AccessEntry
-
-        PATH = "projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
-        DESCRIPTION = "DESCRIPTION"
-        FRIENDLY_NAME = "TITLE"
-        LOCATION = "loc"
-        LABELS = {"priority": "high"}
-        ACCESS = [{"role": "OWNER", "userByEmail": "phred@example.com"}]
-        EXP = 17
-        RESOURCE = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "etag": "etag",
-            "description": DESCRIPTION,
-            "friendlyName": FRIENDLY_NAME,
-            "location": LOCATION,
-            "defaultTableExpirationMs": EXP,
-            "labels": LABELS,
-            "access": ACCESS,
-        }
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(RESOURCE, RESOURCE)
-        ds = Dataset(DatasetReference(self.PROJECT, self.DS_ID))
-        ds.description = DESCRIPTION
-        ds.friendly_name = FRIENDLY_NAME
-        ds.location = LOCATION
-        ds.default_table_expiration_ms = EXP
-        ds.labels = LABELS
-        ds.access_entries = [AccessEntry("OWNER", "userByEmail", "phred@example.com")]
-        fields = [
-            "description",
-            "friendly_name",
-            "location",
-            "labels",
-            "access_entries",
-        ]
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            ds2 = client.update_dataset(ds, fields=fields, timeout=7.5,)
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % PATH, "fields": fields}, client, None
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="PATCH",
-            data={
-                "description": DESCRIPTION,
-                "friendlyName": FRIENDLY_NAME,
-                "location": LOCATION,
-                "labels": LABELS,
-                "access": ACCESS,
-            },
-            path="/" + PATH,
-            headers=None,
-            timeout=7.5,
-        )
-        self.assertEqual(ds2.description, ds.description)
-        self.assertEqual(ds2.friendly_name, ds.friendly_name)
-        self.assertEqual(ds2.location, ds.location)
-        self.assertEqual(ds2.labels, ds.labels)
-        self.assertEqual(ds2.access_entries, ds.access_entries)
-
-        # ETag becomes If-Match header.
-        ds._properties["etag"] = "etag"
-        client.update_dataset(ds, [])
-        req = conn.api_request.call_args
-        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
-
-    def test_update_dataset_w_custom_property(self):
-        # The library should handle sending properties to the API that are not
-        # yet part of the library
-        from google.cloud.bigquery.dataset import Dataset
-
-        path = "/projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
-        resource = {
-            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
-            "newAlphaProperty": "unreleased property",
-        }
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource)
-        dataset = Dataset(DatasetReference(self.PROJECT, self.DS_ID))
-        dataset._properties["newAlphaProperty"] = "unreleased property"
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            dataset = client.update_dataset(dataset, ["newAlphaProperty"])
-
-        final_attributes.assert_called_once_with(
-            {"path": path, "fields": ["newAlphaProperty"]}, client, None
-        )
-
-        conn.api_request.assert_called_once_with(
-            method="PATCH",
-            data={"newAlphaProperty": "unreleased property"},
-            path=path,
-            headers=None,
-            timeout=None,
-        )
-
-        self.assertEqual(dataset.dataset_id, self.DS_ID)
-        self.assertEqual(dataset.project, self.PROJECT)
-        self.assertEqual(dataset._properties["newAlphaProperty"], "unreleased property")
-
-    def test_update_model(self):
-        from google.cloud.bigquery.model import Model
-
-        path = "projects/%s/datasets/%s/models/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.MODEL_ID,
-        )
-        description = "description"
-        title = "title"
-        expires = datetime.datetime(
-            2012, 12, 21, 16, 0, 0, tzinfo=google.cloud._helpers.UTC
-        )
-        resource = {
-            "modelReference": {
-                "projectId": self.PROJECT,
-                "datasetId": self.DS_ID,
-                "modelId": self.MODEL_ID,
-            },
-            "description": description,
-            "etag": "etag",
-            "expirationTime": str(google.cloud._helpers._millis(expires)),
-            "friendlyName": title,
-            "labels": {"x": "y"},
-        }
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource, resource)
-        model_id = "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.MODEL_ID)
-        model = Model(model_id)
-        model.description = description
-        model.friendly_name = title
-        model.expires = expires
-        model.labels = {"x": "y"}
-        fields = ["description", "friendly_name", "labels", "expires"]
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            updated_model = client.update_model(model, fields, timeout=7.5)
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": fields}, client, None
-        )
-
-        sent = {
-            "description": description,
-            "expirationTime": str(google.cloud._helpers._millis(expires)),
-            "friendlyName": title,
-            "labels": {"x": "y"},
-        }
-        conn.api_request.assert_called_once_with(
-            method="PATCH", data=sent, path="/" + path, headers=None, timeout=7.5
-        )
-        self.assertEqual(updated_model.model_id, model.model_id)
-        self.assertEqual(updated_model.description, model.description)
-        self.assertEqual(updated_model.friendly_name, model.friendly_name)
-        self.assertEqual(updated_model.labels, model.labels)
-        self.assertEqual(updated_model.expires, model.expires)
-
-        # ETag becomes If-Match header.
-        model._proto.etag = "etag"
-        client.update_model(model, [])
-        req = conn.api_request.call_args
-        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
-
-    def test_update_routine(self):
-        from google.cloud.bigquery.routine import Routine
-        from google.cloud.bigquery.routine import RoutineArgument
-
-        full_routine_id = "routines-project.test_routines.updated_routine"
-        resource = {
-            "routineReference": {
-                "projectId": "routines-project",
-                "datasetId": "test_routines",
-                "routineId": "updated_routine",
-            },
-            "routineType": "SCALAR_FUNCTION",
-            "language": "SQL",
-            "definitionBody": "x * 3",
-            "arguments": [{"name": "x", "dataType": {"typeKind": "INT64"}}],
-            "returnType": None,
-            "someNewField": "someValue",
-        }
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource, resource)
-        routine = Routine(full_routine_id)
-        routine.arguments = [
-            RoutineArgument(
-                name="x",
-                data_type=bigquery_v2.types.StandardSqlDataType(
-                    type_kind=bigquery_v2.types.StandardSqlDataType.TypeKind.INT64
-                ),
-            )
-        ]
-        routine.body = "x * 3"
-        routine.language = "SQL"
-        routine.type_ = "SCALAR_FUNCTION"
-        routine._properties["someNewField"] = "someValue"
-        fields = [
-            "arguments",
-            "language",
-            "body",
-            "type_",
-            "return_type",
-            "someNewField",
-        ]
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            actual_routine = client.update_routine(routine, fields, timeout=7.5,)
-
-        final_attributes.assert_called_once_with(
-            {"path": routine.path, "fields": fields}, client, None
-        )
-
-        # TODO: routineReference isn't needed when the Routines API supports
-        #       partial updates.
-        sent = resource
-        conn.api_request.assert_called_once_with(
-            method="PUT",
-            data=sent,
-            path="/projects/routines-project/datasets/test_routines/routines/updated_routine",
-            headers=None,
-            timeout=7.5,
-        )
-        self.assertEqual(actual_routine.arguments, routine.arguments)
-        self.assertEqual(actual_routine.body, routine.body)
-        self.assertEqual(actual_routine.language, routine.language)
-        self.assertEqual(actual_routine.type_, routine.type_)
-
-        # ETag becomes If-Match header.
-        routine._properties["etag"] = "im-an-etag"
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            client.update_routine(routine, [])
-
-        final_attributes.assert_called_once_with(
-            {"path": routine.path, "fields": []}, client, None
-        )
-
-        req = conn.api_request.call_args
-        self.assertEqual(req[1]["headers"]["If-Match"], "im-an-etag")
-
-    def test_update_table(self):
-        from google.cloud.bigquery.schema import SchemaField
-        from google.cloud.bigquery.table import Table
-
-        path = "projects/%s/datasets/%s/tables/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-        description = "description"
-        title = "title"
-        resource = self._make_table_resource()
-        resource.update(
-            {
-                "schema": {
-                    "fields": [
-                        {
-                            "name": "full_name",
-                            "type": "STRING",
-                            "mode": "REQUIRED",
-                            "description": None,
-                        },
-                        {
-                            "name": "age",
-                            "type": "INTEGER",
-                            "mode": "REQUIRED",
-                            "description": "New field description",
-                        },
-                    ]
-                },
-                "etag": "etag",
-                "description": description,
-                "friendlyName": title,
-                "labels": {"x": "y"},
-            }
-        )
-        schema = [
-            SchemaField("full_name", "STRING", mode="REQUIRED", description=None),
-            SchemaField(
-                "age", "INTEGER", mode="REQUIRED", description="New field description"
-            ),
-        ]
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource, resource)
-        table = Table(self.TABLE_REF, schema=schema)
-        table.description = description
-        table.friendly_name = title
-        table.labels = {"x": "y"}
-        fields = ["schema", "description", "friendly_name", "labels"]
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            updated_table = client.update_table(table, fields, timeout=7.5)
-        span_path = "/%s" % path
+    def test_get_iam_policy(self):
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_OWNER_ROLE
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_EDITOR_ROLE
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_VIEWER_ROLE
+        from google.api_core.iam import Policy
 
-        final_attributes.assert_called_once_with(
-            {"path": span_path, "fields": fields}, client, None
+        PATH = "/projects/{}/datasets/{}/tables/{}:getIamPolicy".format(
+            self.PROJECT, self.DS_ID, self.TABLE_ID,
         )
-
-        sent = {
-            "schema": {
-                "fields": [
-                    {
-                        "name": "full_name",
-                        "type": "STRING",
-                        "mode": "REQUIRED",
-                        "description": None,
-                    },
-                    {
-                        "name": "age",
-                        "type": "INTEGER",
-                        "mode": "REQUIRED",
-                        "description": "New field description",
-                    },
-                ]
-            },
-            "description": description,
-            "friendlyName": title,
-            "labels": {"x": "y"},
+        BODY = {"options": {"requestedPolicyVersion": 1}}
+        ETAG = "CARDI"
+        VERSION = 1
+        OWNER1 = "user:phred@example.com"
+        OWNER2 = "group:cloud-logs@google.com"
+        EDITOR1 = "domain:google.com"
+        EDITOR2 = "user:phred@example.com"
+        VIEWER1 = "serviceAccount:1234-abcdef@service.example.com"
+        VIEWER2 = "user:phred@example.com"
+        RETURNED = {
+            "resourceId": PATH,
+            "etag": ETAG,
+            "version": VERSION,
+            "bindings": [
+                {"role": BIGQUERY_DATA_OWNER_ROLE, "members": [OWNER1, OWNER2]},
+                {"role": BIGQUERY_DATA_EDITOR_ROLE, "members": [EDITOR1, EDITOR2]},
+                {"role": BIGQUERY_DATA_VIEWER_ROLE, "members": [VIEWER1, VIEWER2]},
+            ],
+        }
+        EXPECTED = {
+            binding["role"]: set(binding["members"]) for binding in RETURNED["bindings"]
         }
-        conn.api_request.assert_called_once_with(
-            method="PATCH", data=sent, path="/" + path, headers=None, timeout=7.5
-        )
-        self.assertEqual(updated_table.description, table.description)
-        self.assertEqual(updated_table.friendly_name, table.friendly_name)
-        self.assertEqual(updated_table.schema, table.schema)
-        self.assertEqual(updated_table.labels, table.labels)
 
-        # ETag becomes If-Match header.
-        table._properties["etag"] = "etag"
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        conn = client._connection = make_connection(RETURNED)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            client.update_table(table, [])
+            policy = client.get_iam_policy(self.TABLE_REF, timeout=7.5)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": []}, client, None
+        final_attributes.assert_called_once_with({"path": PATH}, client, None)
+
+        conn.api_request.assert_called_once_with(
+            method="POST", path=PATH, data=BODY, timeout=7.5
         )
 
-        req = conn.api_request.call_args
-        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
+        self.assertIsInstance(policy, Policy)
+        self.assertEqual(policy.etag, RETURNED["etag"])
+        self.assertEqual(policy.version, RETURNED["version"])
+        self.assertEqual(dict(policy), EXPECTED)
 
-    def test_update_table_w_custom_property(self):
-        from google.cloud.bigquery.table import Table
+    def test_get_iam_policy_w_invalid_table(self):
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
 
-        path = "projects/%s/datasets/%s/tables/%s" % (
+        table_resource_string = "projects/{}/datasets/{}/tables/{}".format(
+            self.PROJECT, self.DS_ID, self.TABLE_ID,
+        )
+
+        with self.assertRaises(TypeError):
+            client.get_iam_policy(table_resource_string)
+
+    def test_get_iam_policy_w_invalid_version(self):
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+
+        with self.assertRaises(ValueError):
+            client.get_iam_policy(self.TABLE_REF, requested_policy_version=2)
+
+    def test_set_iam_policy(self):
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_OWNER_ROLE
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_EDITOR_ROLE
+        from google.cloud.bigquery.iam import BIGQUERY_DATA_VIEWER_ROLE
+        from google.api_core.iam import Policy
+
+        PATH = "/projects/%s/datasets/%s/tables/%s:setIamPolicy" % (
             self.PROJECT,
             self.DS_ID,
             self.TABLE_ID,
         )
-        resource = self._make_table_resource()
-        resource["newAlphaProperty"] = "unreleased property"
+        ETAG = "foo"
+        VERSION = 1
+        OWNER1 = "user:phred@example.com"
+        OWNER2 = "group:cloud-logs@google.com"
+        EDITOR1 = "domain:google.com"
+        EDITOR2 = "user:phred@example.com"
+        VIEWER1 = "serviceAccount:1234-abcdef@service.example.com"
+        VIEWER2 = "user:phred@example.com"
+        BINDINGS = [
+            {"role": BIGQUERY_DATA_OWNER_ROLE, "members": [OWNER1, OWNER2]},
+            {"role": BIGQUERY_DATA_EDITOR_ROLE, "members": [EDITOR1, EDITOR2]},
+            {"role": BIGQUERY_DATA_VIEWER_ROLE, "members": [VIEWER1, VIEWER2]},
+        ]
+        MASK = "bindings,etag"
+        RETURNED = {"etag": ETAG, "version": VERSION, "bindings": BINDINGS}
+
+        policy = Policy()
+        for binding in BINDINGS:
+            policy[binding["role"]] = binding["members"]
+
+        BODY = {"policy": policy.to_api_repr(), "updateMask": MASK}
+
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table._properties["newAlphaProperty"] = "unreleased property"
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        conn = client._connection = make_connection(RETURNED)
 
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            updated_table = client.update_table(table, ["newAlphaProperty"])
+            returned_policy = client.set_iam_policy(
+                self.TABLE_REF, policy, updateMask=MASK, timeout=7.5
+            )
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": ["newAlphaProperty"]}, client, None,
+        final_attributes.assert_called_once_with({"path": PATH}, client, None)
+
+        conn.api_request.assert_called_once_with(
+            method="POST", path=PATH, data=BODY, timeout=7.5
+        )
+        self.assertEqual(returned_policy.etag, ETAG)
+        self.assertEqual(returned_policy.version, VERSION)
+        self.assertEqual(dict(returned_policy), dict(policy))
+
+    def test_set_iam_policy_no_mask(self):
+        from google.api_core.iam import Policy
+
+        PATH = "/projects/%s/datasets/%s/tables/%s:setIamPolicy" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
         )
+        RETURNED = {"etag": "foo", "version": 1, "bindings": []}
+
+        policy = Policy()
+        BODY = {"policy": policy.to_api_repr()}
+
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        conn = client._connection = make_connection(RETURNED)
+        with mock.patch(
+            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+        ) as final_attributes:
+            client.set_iam_policy(self.TABLE_REF, policy, timeout=7.5)
+
+        final_attributes.assert_called_once_with({"path": PATH}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="PATCH",
-            path="/%s" % path,
-            data={"newAlphaProperty": "unreleased property"},
-            headers=None,
-            timeout=None,
+            method="POST", path=PATH, data=BODY, timeout=7.5
         )
-        self.assertEqual(
-            updated_table._properties["newAlphaProperty"], "unreleased property"
+
+    def test_set_iam_policy_invalid_policy(self):
+        from google.api_core.iam import Policy
+
+        policy = Policy()
+        invalid_policy_repr = policy.to_api_repr()
+
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+
+        with self.assertRaises(TypeError):
+            client.set_iam_policy(self.TABLE_REF, invalid_policy_repr)
+
+    def test_set_iam_policy_w_invalid_table(self):
+        from google.api_core.iam import Policy
+
+        policy = Policy()
+
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+
+        table_resource_string = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
         )
 
-    def test_update_table_only_use_legacy_sql(self):
-        from google.cloud.bigquery.table import Table
+        with self.assertRaises(TypeError):
+            client.set_iam_policy(table_resource_string, policy)
 
-        path = "projects/%s/datasets/%s/tables/%s" % (
+    def test_test_iam_permissions(self):
+        PATH = "/projects/%s/datasets/%s/tables/%s:testIamPermissions" % (
             self.PROJECT,
             self.DS_ID,
             self.TABLE_ID,
         )
-        resource = self._make_table_resource()
-        resource["view"] = {"useLegacySql": True}
+
+        PERMISSIONS = ["bigquery.tables.get", "bigquery.tables.update"]
+        BODY = {"permissions": PERMISSIONS}
+        RETURNED = {"permissions": PERMISSIONS}
+
         creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF)
-        table.view_use_legacy_sql = True
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
+        conn = client._connection = make_connection(RETURNED)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            updated_table = client.update_table(table, ["view_use_legacy_sql"])
+            client.test_iam_permissions(self.TABLE_REF, PERMISSIONS, timeout=7.5)
 
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": ["view_use_legacy_sql"]}, client, None,
-        )
+        final_attributes.assert_called_once_with({"path": PATH}, client, None)
 
         conn.api_request.assert_called_once_with(
-            method="PATCH",
-            path="/%s" % path,
-            data={"view": {"useLegacySql": True}},
-            headers=None,
-            timeout=None,
+            method="POST", path=PATH, data=BODY, timeout=7.5
         )
-        self.assertEqual(updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
 
-    def test_update_table_w_query(self):
-        import datetime
-        from google.cloud._helpers import UTC
-        from google.cloud._helpers import _millis
-        from google.cloud.bigquery.schema import SchemaField
-        from google.cloud.bigquery.table import Table
+    def test_test_iam_permissions_w_invalid_table(self):
+        creds = _make_credentials()
+        http = object()
+        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
 
-        path = "projects/%s/datasets/%s/tables/%s" % (
+        table_resource_string = "projects/%s/datasets/%s/tables/%s" % (
             self.PROJECT,
             self.DS_ID,
             self.TABLE_ID,
         )
-        query = "select fullname, age from person_ages"
-        location = "EU"
-        exp_time = datetime.datetime(2015, 8, 1, 23, 59, 59, tzinfo=UTC)
-        schema_resource = {
-            "fields": [
-                {
-                    "name": "full_name",
-                    "type": "STRING",
-                    "mode": "REQUIRED",
-                    "description": None,
-                },
-                {
-                    "name": "age",
-                    "type": "INTEGER",
-                    "mode": "REQUIRED",
-                    "description": "this is a column",
-                },
-                {"name": "country", "type": "STRING", "mode": "NULLABLE"},
-            ]
+
+        PERMISSIONS = ["bigquery.tables.get", "bigquery.tables.update"]
+
+        with self.assertRaises(TypeError):
+            client.test_iam_permissions(table_resource_string, PERMISSIONS)
+
+    def test_update_dataset_w_invalid_field(self):
+        from google.cloud.bigquery.dataset import Dataset
+
+        creds = _make_credentials()
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        with self.assertRaises(ValueError):
+            client.update_dataset(
+                Dataset("{}.{}".format(self.PROJECT, self.DS_ID)), ["foo"]
+            )
+
+    def test_update_dataset(self):
+        from google.cloud.bigquery.dataset import Dataset, AccessEntry
+
+        PATH = "projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
+        DESCRIPTION = "DESCRIPTION"
+        FRIENDLY_NAME = "TITLE"
+        LOCATION = "loc"
+        LABELS = {"priority": "high"}
+        ACCESS = [{"role": "OWNER", "userByEmail": "phred@example.com"}]
+        EXP = 17
+        RESOURCE = {
+            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
+            "etag": "etag",
+            "description": DESCRIPTION,
+            "friendlyName": FRIENDLY_NAME,
+            "location": LOCATION,
+            "defaultTableExpirationMs": EXP,
+            "labels": LABELS,
+            "access": ACCESS,
         }
-        schema = [
-            SchemaField(
-                "full_name",
-                "STRING",
-                mode="REQUIRED",
-                # Explicitly unset the description.
-                description=None,
-            ),
-            SchemaField(
-                "age", "INTEGER", mode="REQUIRED", description="this is a column"
-            ),
-            # Omit the description to not make updates to it.
-            SchemaField("country", "STRING"),
-        ]
-        resource = self._make_table_resource()
-        resource.update(
-            {
-                "schema": schema_resource,
-                "view": {"query": query, "useLegacySql": True},
-                "location": location,
-                "expirationTime": _millis(exp_time),
-            }
-        )
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource)
-        table = Table(self.TABLE_REF, schema=schema)
-        table.expires = exp_time
-        table.view_query = query
-        table.view_use_legacy_sql = True
-        updated_properties = ["schema", "view_query", "expires", "view_use_legacy_sql"]
+        conn = client._connection = make_connection(RESOURCE, RESOURCE)
+        ds = Dataset(DatasetReference(self.PROJECT, self.DS_ID))
+        ds.description = DESCRIPTION
+        ds.friendly_name = FRIENDLY_NAME
+        ds.location = LOCATION
+        ds.default_table_expiration_ms = EXP
+        ds.labels = LABELS
+        ds.access_entries = [AccessEntry("OWNER", "userByEmail", "phred@example.com")]
+        fields = [
+            "description",
+            "friendly_name",
+            "location",
+            "labels",
+            "access_entries",
+        ]
+
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            updated_table = client.update_table(table, updated_properties)
+            ds2 = client.update_dataset(ds, fields=fields, timeout=7.5,)
 
         final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": updated_properties}, client, None,
+            {"path": "/%s" % PATH, "fields": fields}, client, None
         )
 
-        self.assertEqual(updated_table.schema, table.schema)
-        self.assertEqual(updated_table.view_query, table.view_query)
-        self.assertEqual(updated_table.expires, table.expires)
-        self.assertEqual(updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
-        self.assertEqual(updated_table.location, location)
-
         conn.api_request.assert_called_once_with(
             method="PATCH",
-            path="/%s" % path,
             data={
-                "view": {"query": query, "useLegacySql": True},
-                "expirationTime": str(_millis(exp_time)),
-                "schema": schema_resource,
+                "description": DESCRIPTION,
+                "friendlyName": FRIENDLY_NAME,
+                "location": LOCATION,
+                "labels": LABELS,
+                "access": ACCESS,
             },
+            path="/" + PATH,
             headers=None,
-            timeout=None,
+            timeout=7.5,
         )
+        self.assertEqual(ds2.description, ds.description)
+        self.assertEqual(ds2.friendly_name, ds.friendly_name)
+        self.assertEqual(ds2.location, ds.location)
+        self.assertEqual(ds2.labels, ds.labels)
+        self.assertEqual(ds2.access_entries, ds.access_entries)
 
-    def test_update_table_w_schema_None(self):
-        # Simulate deleting schema:  not sure if back-end will actually
-        # allow this operation, but the spec says it is optional.
-        path = "projects/%s/datasets/%s/tables/%s" % (
-            self.PROJECT,
-            self.DS_ID,
-            self.TABLE_ID,
-        )
-        resource1 = self._make_table_resource()
-        resource1.update(
-            {
-                "schema": {
-                    "fields": [
-                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
-                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
-                    ]
-                }
-            }
-        )
-        resource2 = self._make_table_resource()
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource1, resource2)
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            table = client.get_table(
-                # Test with string for table ID
-                "{}.{}.{}".format(
-                    self.TABLE_REF.project,
-                    self.TABLE_REF.dataset_id,
-                    self.TABLE_REF.table_id,
-                )
-            )
+        # ETag becomes If-Match header.
+        ds._properties["etag"] = "etag"
+        client.update_dataset(ds, [])
+        req = conn.api_request.call_args
+        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
 
-        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
+    def test_update_dataset_w_custom_property(self):
+        # The library should handle sending properties to the API that are not
+        # yet part of the library
+        from google.cloud.bigquery.dataset import Dataset
 
-        table.schema = None
+        path = "/projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
+        resource = {
+            "datasetReference": {"projectId": self.PROJECT, "datasetId": self.DS_ID},
+            "newAlphaProperty": "unreleased property",
+        }
+        creds = _make_credentials()
+        client = self._make_one(project=self.PROJECT, credentials=creds)
+        conn = client._connection = make_connection(resource)
+        dataset = Dataset(DatasetReference(self.PROJECT, self.DS_ID))
+        dataset._properties["newAlphaProperty"] = "unreleased property"
 
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            updated_table = client.update_table(table, ["schema"])
+            dataset = client.update_dataset(dataset, ["newAlphaProperty"])
 
         final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": ["schema"]}, client, None
+            {"path": path, "fields": ["newAlphaProperty"]}, client, None
         )
 
-        self.assertEqual(len(conn.api_request.call_args_list), 2)
-        req = conn.api_request.call_args_list[1]
-        self.assertEqual(req[1]["method"], "PATCH")
-        sent = {"schema": None}
-        self.assertEqual(req[1]["data"], sent)
-        self.assertEqual(req[1]["path"], "/%s" % path)
-        self.assertEqual(len(updated_table.schema), 0)
+        conn.api_request.assert_called_once_with(
+            method="PATCH",
+            data={"newAlphaProperty": "unreleased property"},
+            path=path,
+            headers=None,
+            timeout=None,
+        )
 
-    def test_update_table_delete_property(self):
-        from google.cloud.bigquery.table import Table
+        self.assertEqual(dataset.dataset_id, self.DS_ID)
+        self.assertEqual(dataset.project, self.PROJECT)
+        self.assertEqual(dataset._properties["newAlphaProperty"], "unreleased property")
 
-        description = "description"
-        title = "title"
-        path = "projects/%s/datasets/%s/tables/%s" % (
+    def test_update_model(self):
+        from google.cloud.bigquery.model import Model
+
+        path = "projects/%s/datasets/%s/models/%s" % (
             self.PROJECT,
             self.DS_ID,
-            self.TABLE_ID,
+            self.MODEL_ID,
         )
-        resource1 = self._make_table_resource()
-        resource1.update({"description": description, "friendlyName": title})
-        resource2 = self._make_table_resource()
-        resource2["description"] = None
+        description = "description"
+        title = "title"
+        expires = datetime.datetime(
+            2012, 12, 21, 16, 0, 0, tzinfo=google.cloud._helpers.UTC
+        )
+        resource = {
+            "modelReference": {
+                "projectId": self.PROJECT,
+                "datasetId": self.DS_ID,
+                "modelId": self.MODEL_ID,
+            },
+            "description": description,
+            "etag": "etag",
+            "expirationTime": str(google.cloud._helpers._millis(expires)),
+            "friendlyName": title,
+            "labels": {"x": "y"},
+        }
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(resource1, resource2)
-        table = Table(self.TABLE_REF)
-        table.description = description
-        table.friendly_name = title
-
+        conn = client._connection = make_connection(resource, resource)
+        model_id = "{}.{}.{}".format(self.PROJECT, self.DS_ID, self.MODEL_ID)
+        model = Model(model_id)
+        model.description = description
+        model.friendly_name = title
+        model.expires = expires
+        model.labels = {"x": "y"}
+        fields = ["description", "friendly_name", "labels", "expires"]
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            table2 = client.update_table(table, ["description", "friendly_name"])
+            updated_model = client.update_model(model, fields, timeout=7.5)
 
         final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": ["description", "friendly_name"]},
-            client,
-            None,
+            {"path": "/%s" % path, "fields": fields}, client, None
         )
 
-        self.assertEqual(table2.description, table.description)
-        table2.description = None
-
-        with mock.patch(
-            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-        ) as final_attributes:
-            table3 = client.update_table(table2, ["description"])
-
-        final_attributes.assert_called_once_with(
-            {"path": "/%s" % path, "fields": ["description"]}, client, None
+        sent = {
+            "description": description,
+            "expirationTime": str(google.cloud._helpers._millis(expires)),
+            "friendlyName": title,
+            "labels": {"x": "y"},
+        }
+        conn.api_request.assert_called_once_with(
+            method="PATCH", data=sent, path="/" + path, headers=None, timeout=7.5
         )
+        self.assertEqual(updated_model.model_id, model.model_id)
+        self.assertEqual(updated_model.description, model.description)
+        self.assertEqual(updated_model.friendly_name, model.friendly_name)
+        self.assertEqual(updated_model.labels, model.labels)
+        self.assertEqual(updated_model.expires, model.expires)
 
-        self.assertEqual(len(conn.api_request.call_args_list), 2)
-        req = conn.api_request.call_args_list[1]
-        self.assertEqual(req[1]["method"], "PATCH")
-        self.assertEqual(req[1]["path"], "/%s" % path)
-        sent = {"description": None}
-        self.assertEqual(req[1]["data"], sent)
-        self.assertIsNone(table3.description)
+        # ETag becomes If-Match header.
+        model._proto.etag = "etag"
+        client.update_model(model, [])
+        req = conn.api_request.call_args
+        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
 
-    def test_list_tables_empty_w_timeout(self):
-        path = "/projects/{}/datasets/{}/tables".format(self.PROJECT, self.DS_ID)
+    def test_update_routine(self):
+        from google.cloud.bigquery.routine import Routine
+        from google.cloud.bigquery.routine import RoutineArgument
+
+        full_routine_id = "routines-project.test_routines.updated_routine"
+        resource = {
+            "routineReference": {
+                "projectId": "routines-project",
+                "datasetId": "test_routines",
+                "routineId": "updated_routine",
+            },
+            "routineType": "SCALAR_FUNCTION",
+            "language": "SQL",
+            "definitionBody": "x * 3",
+            "arguments": [{"name": "x", "dataType": {"typeKind": "INT64"}}],
+            "returnType": None,
+            "someNewField": "someValue",
+        }
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection({})
+        conn = client._connection = make_connection(resource, resource)
+        routine = Routine(full_routine_id)
+        routine.arguments = [
+            RoutineArgument(
+                name="x",
+                data_type=bigquery_v2.types.StandardSqlDataType(
+                    type_kind=bigquery_v2.types.StandardSqlDataType.TypeKind.INT64
+                ),
+            )
+        ]
+        routine.body = "x * 3"
+        routine.language = "SQL"
+        routine.type_ = "SCALAR_FUNCTION"
+        routine._properties["someNewField"] = "someValue"
+        fields = [
+            "arguments",
+            "language",
+            "body",
+            "type_",
+            "return_type",
+            "someNewField",
+        ]
 
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-        iterator = client.list_tables(dataset, timeout=7.5)
-        self.assertIs(iterator.dataset, dataset)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
+            actual_routine = client.update_routine(routine, fields, timeout=7.5,)
 
-        final_attributes.assert_called_once_with({"path": path}, client, None)
-        tables = list(page)
-        token = iterator.next_page_token
+        final_attributes.assert_called_once_with(
+            {"path": routine.path, "fields": fields}, client, None
+        )
 
-        self.assertEqual(tables, [])
-        self.assertIsNone(token)
+        # TODO: routineReference isn't needed when the Routines API supports
+        #       partial updates.
+        sent = resource
         conn.api_request.assert_called_once_with(
-            method="GET", path=path, query_params={}, timeout=7.5
+            method="PUT",
+            data=sent,
+            path="/projects/routines-project/datasets/test_routines/routines/updated_routine",
+            headers=None,
+            timeout=7.5,
         )
+        self.assertEqual(actual_routine.arguments, routine.arguments)
+        self.assertEqual(actual_routine.body, routine.body)
+        self.assertEqual(actual_routine.language, routine.language)
+        self.assertEqual(actual_routine.type_, routine.type_)
 
-    def test_list_models_empty_w_timeout(self):
-        path = "/projects/{}/datasets/{}/models".format(self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection({})
-
-        dataset_id = "{}.{}".format(self.PROJECT, self.DS_ID)
-        iterator = client.list_models(dataset_id, timeout=7.5)
+        # ETag becomes If-Match header.
+        routine._properties["etag"] = "im-an-etag"
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
-        models = list(page)
-        token = iterator.next_page_token
+            client.update_routine(routine, [])
 
-        self.assertEqual(models, [])
-        self.assertIsNone(token)
-        conn.api_request.assert_called_once_with(
-            method="GET", path=path, query_params={}, timeout=7.5
+        final_attributes.assert_called_once_with(
+            {"path": routine.path, "fields": []}, client, None
         )
 
-    def test_list_models_defaults(self):
-        from google.cloud.bigquery.model import Model
+        req = conn.api_request.call_args
+        self.assertEqual(req[1]["headers"]["If-Match"], "im-an-etag")
 
-        MODEL_1 = "model_one"
-        MODEL_2 = "model_two"
-        PATH = "projects/%s/datasets/%s/models" % (self.PROJECT, self.DS_ID)
-        TOKEN = "TOKEN"
-        DATA = {
-            "nextPageToken": TOKEN,
-            "models": [
-                {
-                    "modelReference": {
-                        "modelId": MODEL_1,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    }
-                },
-                {
-                    "modelReference": {
-                        "modelId": MODEL_2,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    }
-                },
-            ],
-        }
+    def test_update_table(self):
+        from google.cloud.bigquery.schema import SchemaField
+        from google.cloud.bigquery.table import Table
 
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        description = "description"
+        title = "title"
+        resource = self._make_table_resource()
+        resource.update(
+            {
+                "schema": {
+                    "fields": [
+                        {
+                            "name": "full_name",
+                            "type": "STRING",
+                            "mode": "REQUIRED",
+                            "description": None,
+                        },
+                        {
+                            "name": "age",
+                            "type": "INTEGER",
+                            "mode": "REQUIRED",
+                            "description": "New field description",
+                        },
+                    ]
+                },
+                "etag": "etag",
+                "description": description,
+                "friendlyName": title,
+                "labels": {"x": "y"},
+            }
+        )
+        schema = [
+            SchemaField("full_name", "STRING", mode="REQUIRED", description=None),
+            SchemaField(
+                "age", "INTEGER", mode="REQUIRED", description="New field description"
+            ),
+        ]
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(DATA)
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-
-        iterator = client.list_models(dataset)
-        self.assertIs(iterator.dataset, dataset)
+        conn = client._connection = make_connection(resource, resource)
+        table = Table(self.TABLE_REF, schema=schema)
+        table.description = description
+        table.friendly_name = title
+        table.labels = {"x": "y"}
+        fields = ["schema", "description", "friendly_name", "labels"]
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
-        models = list(page)
-        token = iterator.next_page_token
+            updated_table = client.update_table(table, fields, timeout=7.5)
+        span_path = "/%s" % path
 
-        self.assertEqual(len(models), len(DATA["models"]))
-        for found, expected in zip(models, DATA["models"]):
-            self.assertIsInstance(found, Model)
-            self.assertEqual(found.model_id, expected["modelReference"]["modelId"])
-        self.assertEqual(token, TOKEN)
+        final_attributes.assert_called_once_with(
+            {"path": span_path, "fields": fields}, client, None
+        )
 
+        sent = {
+            "schema": {
+                "fields": [
+                    {
+                        "name": "full_name",
+                        "type": "STRING",
+                        "mode": "REQUIRED",
+                        "description": None,
+                    },
+                    {
+                        "name": "age",
+                        "type": "INTEGER",
+                        "mode": "REQUIRED",
+                        "description": "New field description",
+                    },
+                ]
+            },
+            "description": description,
+            "friendlyName": title,
+            "labels": {"x": "y"},
+        }
         conn.api_request.assert_called_once_with(
-            method="GET", path="/%s" % PATH, query_params={}, timeout=None
+            method="PATCH", data=sent, path="/" + path, headers=None, timeout=7.5
         )
+        self.assertEqual(updated_table.description, table.description)
+        self.assertEqual(updated_table.friendly_name, table.friendly_name)
+        self.assertEqual(updated_table.schema, table.schema)
+        self.assertEqual(updated_table.labels, table.labels)
 
-    def test_list_models_wrong_type(self):
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        with self.assertRaises(TypeError):
-            client.list_models(DatasetReference(self.PROJECT, self.DS_ID).model("foo"))
-
-    def test_list_routines_empty_w_timeout(self):
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection({})
-
-        iterator = client.list_routines("test-routines.test_routines", timeout=7.5)
+        # ETag becomes If-Match header.
+        table._properties["etag"] = "etag"
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
+            client.update_table(table, [])
 
         final_attributes.assert_called_once_with(
-            {"path": "/projects/test-routines/datasets/test_routines/routines"},
-            client,
-            None,
-        )
-        routines = list(page)
-        token = iterator.next_page_token
-
-        self.assertEqual(routines, [])
-        self.assertIsNone(token)
-        conn.api_request.assert_called_once_with(
-            method="GET",
-            path="/projects/test-routines/datasets/test_routines/routines",
-            query_params={},
-            timeout=7.5,
+            {"path": "/%s" % path, "fields": []}, client, None
         )
 
-    def test_list_routines_defaults(self):
-        from google.cloud.bigquery.routine import Routine
+        req = conn.api_request.call_args
+        self.assertEqual(req[1]["headers"]["If-Match"], "etag")
 
-        project_id = "test-routines"
-        dataset_id = "test_routines"
-        path = "/projects/test-routines/datasets/test_routines/routines"
-        routine_1 = "routine_one"
-        routine_2 = "routine_two"
-        token = "TOKEN"
-        resource = {
-            "nextPageToken": token,
-            "routines": [
-                {
-                    "routineReference": {
-                        "routineId": routine_1,
-                        "datasetId": dataset_id,
-                        "projectId": project_id,
-                    }
-                },
-                {
-                    "routineReference": {
-                        "routineId": routine_2,
-                        "datasetId": dataset_id,
-                        "projectId": project_id,
-                    }
-                },
-            ],
-        }
+    def test_update_table_w_custom_property(self):
+        from google.cloud.bigquery.table import Table
 
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        resource = self._make_table_resource()
+        resource["newAlphaProperty"] = "unreleased property"
         creds = _make_credentials()
-        client = self._make_one(project=project_id, credentials=creds)
+        client = self._make_one(project=self.PROJECT, credentials=creds)
         conn = client._connection = make_connection(resource)
-        dataset = DatasetReference(client.project, dataset_id)
+        table = Table(self.TABLE_REF)
+        table._properties["newAlphaProperty"] = "unreleased property"
 
-        iterator = client.list_routines(dataset)
-        self.assertIs(iterator.dataset, dataset)
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
-        routines = list(page)
-        actual_token = iterator.next_page_token
+            updated_table = client.update_table(table, ["newAlphaProperty"])
 
-        self.assertEqual(len(routines), len(resource["routines"]))
-        for found, expected in zip(routines, resource["routines"]):
-            self.assertIsInstance(found, Routine)
-            self.assertEqual(
-                found.routine_id, expected["routineReference"]["routineId"]
-            )
-        self.assertEqual(actual_token, token)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": ["newAlphaProperty"]}, client, None,
+        )
 
         conn.api_request.assert_called_once_with(
-            method="GET", path=path, query_params={}, timeout=None
+            method="PATCH",
+            path="/%s" % path,
+            data={"newAlphaProperty": "unreleased property"},
+            headers=None,
+            timeout=None,
+        )
+        self.assertEqual(
+            updated_table._properties["newAlphaProperty"], "unreleased property"
         )
 
-    def test_list_routines_wrong_type(self):
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        with self.assertRaises(TypeError):
-            client.list_routines(
-                DatasetReference(self.PROJECT, self.DS_ID).table("foo")
-            )
-
-    def test_list_tables_defaults(self):
-        from google.cloud.bigquery.table import TableListItem
-
-        TABLE_1 = "table_one"
-        TABLE_2 = "table_two"
-        PATH = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        TOKEN = "TOKEN"
-        DATA = {
-            "nextPageToken": TOKEN,
-            "tables": [
-                {
-                    "kind": "bigquery#table",
-                    "id": "%s:%s.%s" % (self.PROJECT, self.DS_ID, TABLE_1),
-                    "tableReference": {
-                        "tableId": TABLE_1,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    },
-                    "type": "TABLE",
-                },
-                {
-                    "kind": "bigquery#table",
-                    "id": "%s:%s.%s" % (self.PROJECT, self.DS_ID, TABLE_2),
-                    "tableReference": {
-                        "tableId": TABLE_2,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    },
-                    "type": "TABLE",
-                },
-            ],
-        }
+    def test_update_table_only_use_legacy_sql(self):
+        from google.cloud.bigquery.table import Table
 
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        resource = self._make_table_resource()
+        resource["view"] = {"useLegacySql": True}
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(DATA)
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-
-        iterator = client.list_tables(dataset)
-        self.assertIs(iterator.dataset, dataset)
+        conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF)
+        table.view_use_legacy_sql = True
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
-
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
-        tables = list(page)
-        token = iterator.next_page_token
+            updated_table = client.update_table(table, ["view_use_legacy_sql"])
 
-        self.assertEqual(len(tables), len(DATA["tables"]))
-        for found, expected in zip(tables, DATA["tables"]):
-            self.assertIsInstance(found, TableListItem)
-            self.assertEqual(found.full_table_id, expected["id"])
-            self.assertEqual(found.table_type, expected["type"])
-        self.assertEqual(token, TOKEN)
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": ["view_use_legacy_sql"]}, client, None,
+        )
 
         conn.api_request.assert_called_once_with(
-            method="GET", path="/%s" % PATH, query_params={}, timeout=None
+            method="PATCH",
+            path="/%s" % path,
+            data={"view": {"useLegacySql": True}},
+            headers=None,
+            timeout=None,
         )
+        self.assertEqual(updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
 
-    def test_list_tables_explicit(self):
-        from google.cloud.bigquery.table import TableListItem
+    def test_update_table_w_query(self):
+        import datetime
+        from google.cloud._helpers import UTC
+        from google.cloud._helpers import _millis
+        from google.cloud.bigquery.schema import SchemaField
+        from google.cloud.bigquery.table import Table
 
-        TABLE_1 = "table_one"
-        TABLE_2 = "table_two"
-        PATH = "projects/%s/datasets/%s/tables" % (self.PROJECT, self.DS_ID)
-        TOKEN = "TOKEN"
-        DATA = {
-            "tables": [
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        query = "select fullname, age from person_ages"
+        location = "EU"
+        exp_time = datetime.datetime(2015, 8, 1, 23, 59, 59, tzinfo=UTC)
+        schema_resource = {
+            "fields": [
                 {
-                    "kind": "bigquery#dataset",
-                    "id": "%s:%s.%s" % (self.PROJECT, self.DS_ID, TABLE_1),
-                    "tableReference": {
-                        "tableId": TABLE_1,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    },
-                    "type": "TABLE",
+                    "name": "full_name",
+                    "type": "STRING",
+                    "mode": "REQUIRED",
+                    "description": None,
                 },
                 {
-                    "kind": "bigquery#dataset",
-                    "id": "%s:%s.%s" % (self.PROJECT, self.DS_ID, TABLE_2),
-                    "tableReference": {
-                        "tableId": TABLE_2,
-                        "datasetId": self.DS_ID,
-                        "projectId": self.PROJECT,
-                    },
-                    "type": "TABLE",
+                    "name": "age",
+                    "type": "INTEGER",
+                    "mode": "REQUIRED",
+                    "description": "this is a column",
                 },
+                {"name": "country", "type": "STRING", "mode": "NULLABLE"},
             ]
         }
-
+        schema = [
+            SchemaField(
+                "full_name",
+                "STRING",
+                mode="REQUIRED",
+                # Explicitly unset the description.
+                description=None,
+            ),
+            SchemaField(
+                "age", "INTEGER", mode="REQUIRED", description="this is a column"
+            ),
+            # Omit the description to not make updates to it.
+            SchemaField("country", "STRING"),
+        ]
+        resource = self._make_table_resource()
+        resource.update(
+            {
+                "schema": schema_resource,
+                "view": {"query": query, "useLegacySql": True},
+                "location": location,
+                "expirationTime": _millis(exp_time),
+            }
+        )
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(DATA)
-        dataset = DatasetReference(self.PROJECT, self.DS_ID)
-
-        iterator = client.list_tables(
-            # Test with string for dataset ID.
-            self.DS_ID,
-            max_results=3,
-            page_token=TOKEN,
-        )
-        self.assertEqual(iterator.dataset, dataset)
+        conn = client._connection = make_connection(resource)
+        table = Table(self.TABLE_REF, schema=schema)
+        table.expires = exp_time
+        table.view_query = query
+        table.view_use_legacy_sql = True
+        updated_properties = ["schema", "view_query", "expires", "view_use_legacy_sql"]
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            page = next(iterator.pages)
+            updated_table = client.update_table(table, updated_properties)
 
-        final_attributes.assert_called_once_with({"path": "/%s" % PATH}, client, None)
-        tables = list(page)
-        token = iterator.next_page_token
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": updated_properties}, client, None,
+        )
 
-        self.assertEqual(len(tables), len(DATA["tables"]))
-        for found, expected in zip(tables, DATA["tables"]):
-            self.assertIsInstance(found, TableListItem)
-            self.assertEqual(found.full_table_id, expected["id"])
-            self.assertEqual(found.table_type, expected["type"])
-        self.assertIsNone(token)
+        self.assertEqual(updated_table.schema, table.schema)
+        self.assertEqual(updated_table.view_query, table.view_query)
+        self.assertEqual(updated_table.expires, table.expires)
+        self.assertEqual(updated_table.view_use_legacy_sql, table.view_use_legacy_sql)
+        self.assertEqual(updated_table.location, location)
 
         conn.api_request.assert_called_once_with(
-            method="GET",
-            path="/%s" % PATH,
-            query_params={"maxResults": 3, "pageToken": TOKEN},
+            method="PATCH",
+            path="/%s" % path,
+            data={
+                "view": {"query": query, "useLegacySql": True},
+                "expirationTime": str(_millis(exp_time)),
+                "schema": schema_resource,
+            },
+            headers=None,
             timeout=None,
         )
 
-    def test_list_tables_wrong_type(self):
+    def test_update_table_w_schema_None(self):
+        # Simulate deleting schema:  not sure if back-end will actually
+        # allow this operation, but the spec says it is optional.
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        resource1 = self._make_table_resource()
+        resource1.update(
+            {
+                "schema": {
+                    "fields": [
+                        {"name": "full_name", "type": "STRING", "mode": "REQUIRED"},
+                        {"name": "age", "type": "INTEGER", "mode": "REQUIRED"},
+                    ]
+                }
+            }
+        )
+        resource2 = self._make_table_resource()
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        with self.assertRaises(TypeError):
-            client.list_tables(DatasetReference(self.PROJECT, self.DS_ID).table("foo"))
-
-    def test_delete_dataset(self):
-        from google.cloud.bigquery.dataset import Dataset
-        from google.cloud.bigquery.dataset import DatasetReference
+        conn = client._connection = make_connection(resource1, resource2)
+        with mock.patch(
+            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+        ) as final_attributes:
+            table = client.get_table(
+                # Test with string for table ID
+                "{}.{}.{}".format(
+                    self.TABLE_REF.project,
+                    self.TABLE_REF.dataset_id,
+                    self.TABLE_REF.table_id,
+                )
+            )
 
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        datasets = (ds_ref, Dataset(ds_ref), "{}.{}".format(self.PROJECT, self.DS_ID))
-        PATH = "projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection(*([{}] * len(datasets)))
-        for arg in datasets:
-            with mock.patch(
-                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-            ) as final_attributes:
-                client.delete_dataset(arg, timeout=7.5)
+        final_attributes.assert_called_once_with({"path": "/%s" % path}, client, None)
 
-            final_attributes.assert_called_once_with(
-                {"path": "/%s" % PATH}, client, None
-            )
+        table.schema = None
 
-            conn.api_request.assert_called_with(
-                method="DELETE", path="/%s" % PATH, query_params={}, timeout=7.5
-            )
+        with mock.patch(
+            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+        ) as final_attributes:
+            updated_table = client.update_table(table, ["schema"])
 
-    def test_delete_dataset_delete_contents(self):
-        from google.cloud.bigquery.dataset import Dataset
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": ["schema"]}, client, None
+        )
 
-        PATH = "projects/%s/datasets/%s" % (self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        client = self._make_one(project=self.PROJECT, credentials=creds)
-        conn = client._connection = make_connection({}, {})
-        ds_ref = DatasetReference(self.PROJECT, self.DS_ID)
-        for arg in (ds_ref, Dataset(ds_ref)):
-            with mock.patch(
-                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-            ) as final_attributes:
-                client.delete_dataset(arg, delete_contents=True)
+        self.assertEqual(len(conn.api_request.call_args_list), 2)
+        req = conn.api_request.call_args_list[1]
+        self.assertEqual(req[1]["method"], "PATCH")
+        sent = {"schema": None}
+        self.assertEqual(req[1]["data"], sent)
+        self.assertEqual(req[1]["path"], "/%s" % path)
+        self.assertEqual(len(updated_table.schema), 0)
 
-            final_attributes.assert_called_once_with(
-                {"path": "/%s" % PATH, "deleteContents": True}, client, None
-            )
-            conn.api_request.assert_called_with(
-                method="DELETE",
-                path="/%s" % PATH,
-                query_params={"deleteContents": "true"},
-                timeout=None,
-            )
+    def test_update_table_delete_property(self):
+        from google.cloud.bigquery.table import Table
 
-    def test_delete_dataset_wrong_type(self):
+        description = "description"
+        title = "title"
+        path = "projects/%s/datasets/%s/tables/%s" % (
+            self.PROJECT,
+            self.DS_ID,
+            self.TABLE_ID,
+        )
+        resource1 = self._make_table_resource()
+        resource1.update({"description": description, "friendlyName": title})
+        resource2 = self._make_table_resource()
+        resource2["description"] = None
         creds = _make_credentials()
         client = self._make_one(project=self.PROJECT, credentials=creds)
-        with self.assertRaises(TypeError):
-            client.delete_dataset(
-                DatasetReference(self.PROJECT, self.DS_ID).table("foo")
-            )
-
-    def test_delete_dataset_w_not_found_ok_false(self):
-        path = "/projects/{}/datasets/{}".format(self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.NotFound("dataset not found")
-        )
-
-        with self.assertRaises(google.api_core.exceptions.NotFound):
-            with mock.patch(
-                "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
-            ) as final_attributes:
-                client.delete_dataset(self.DS_ID)
+        conn = client._connection = make_connection(resource1, resource2)
+        table = Table(self.TABLE_REF)
+        table.description = description
+        table.friendly_name = title
 
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+        with mock.patch(
+            "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+        ) as final_attributes:
+            table2 = client.update_table(table, ["description", "friendly_name"])
 
-        conn.api_request.assert_called_with(
-            method="DELETE", path=path, query_params={}, timeout=None
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": ["description", "friendly_name"]},
+            client,
+            None,
         )
 
-    def test_delete_dataset_w_not_found_ok_true(self):
-        path = "/projects/{}/datasets/{}".format(self.PROJECT, self.DS_ID)
-        creds = _make_credentials()
-        http = object()
-        client = self._make_one(project=self.PROJECT, credentials=creds, _http=http)
-        conn = client._connection = make_connection(
-            google.api_core.exceptions.NotFound("dataset not found")
-        )
+        self.assertEqual(table2.description, table.description)
+        table2.description = None
 
         with mock.patch(
             "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
         ) as final_attributes:
-            client.delete_dataset(self.DS_ID, not_found_ok=True)
-
-        final_attributes.assert_called_once_with({"path": path}, client, None)
+            table3 = client.update_table(table2, ["description"])
 
-        conn.api_request.assert_called_with(
-            method="DELETE", path=path, query_params={}, timeout=None
+        final_attributes.assert_called_once_with(
+            {"path": "/%s" % path, "fields": ["description"]}, client, None
         )
 
+        self.assertEqual(len(conn.api_request.call_args_list), 2)
+        req = conn.api_request.call_args_list[1]
+        self.assertEqual(req[1]["method"], "PATCH")
+        self.assertEqual(req[1]["path"], "/%s" % path)
+        sent = {"description": None}
+        self.assertEqual(req[1]["data"], sent)
+        self.assertIsNone(table3.description)
+
     def test_delete_model(self):
         from google.cloud.bigquery.model import Model
 
diff --git a/tests/unit/test_create_dataset.py b/tests/unit/test_create_dataset.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_create_dataset.py
@@ -0,0 +1,349 @@
+from google.cloud.bigquery.dataset import Dataset, DatasetReference
+from .helpers import make_connection, dataset_polymorphic, make_client
+import google.cloud.bigquery.dataset
+import mock
+import pytest
+
+
+@dataset_polymorphic
+def test_create_dataset_minimal(make_dataset, get_reference, client, PROJECT, DS_ID):
+    PATH = "projects/%s/datasets" % PROJECT
+    RESOURCE = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+    }
+    conn = client._connection = make_connection(RESOURCE)
+
+    dataset = make_dataset(PROJECT, DS_ID)
+    after = client.create_dataset(dataset, timeout=7.5)
+
+    assert after.dataset_id == DS_ID
+    assert after.project == PROJECT
+    assert after.etag == RESOURCE["etag"]
+    assert after.full_dataset_id == RESOURCE["id"]
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path="/%s" % PATH,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+        },
+        timeout=7.5,
+    )
+
+
+def test_create_dataset_w_attrs(client, PROJECT, DS_ID):
+    from google.cloud.bigquery.dataset import AccessEntry
+
+    PATH = "projects/%s/datasets" % PROJECT
+    DESCRIPTION = "DESC"
+    FRIENDLY_NAME = "FN"
+    LOCATION = "US"
+    USER_EMAIL = "phred@example.com"
+    LABELS = {"color": "red"}
+    VIEW = {
+        "projectId": "my-proj",
+        "datasetId": "starry-skies",
+        "tableId": "northern-hemisphere",
+    }
+    RESOURCE = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "description": DESCRIPTION,
+        "friendlyName": FRIENDLY_NAME,
+        "location": LOCATION,
+        "defaultTableExpirationMs": "3600",
+        "labels": LABELS,
+        "access": [{"role": "OWNER", "userByEmail": USER_EMAIL}, {"view": VIEW}],
+    }
+    conn = client._connection = make_connection(RESOURCE)
+    entries = [
+        AccessEntry("OWNER", "userByEmail", USER_EMAIL),
+        AccessEntry(None, "view", VIEW),
+    ]
+
+    ds_ref = DatasetReference(PROJECT, DS_ID)
+    before = Dataset(ds_ref)
+    before.access_entries = entries
+    before.description = DESCRIPTION
+    before.friendly_name = FRIENDLY_NAME
+    before.default_table_expiration_ms = 3600
+    before.location = LOCATION
+    before.labels = LABELS
+    after = client.create_dataset(before)
+
+    assert after.dataset_id == DS_ID
+    assert after.project == PROJECT
+    assert after.etag == RESOURCE["etag"]
+    assert after.full_dataset_id == RESOURCE["id"]
+    assert after.description == DESCRIPTION
+    assert after.friendly_name == FRIENDLY_NAME
+    assert after.location == LOCATION
+    assert after.default_table_expiration_ms == 3600
+    assert after.labels == LABELS
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path="/%s" % PATH,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "description": DESCRIPTION,
+            "friendlyName": FRIENDLY_NAME,
+            "location": LOCATION,
+            "defaultTableExpirationMs": "3600",
+            "access": [{"role": "OWNER", "userByEmail": USER_EMAIL}, {"view": VIEW}],
+            "labels": LABELS,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_custom_property(client, PROJECT, DS_ID):
+    # The library should handle sending properties to the API that are not
+    # yet part of the library
+
+    path = "/projects/%s/datasets" % PROJECT
+    resource = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "newAlphaProperty": "unreleased property",
+    }
+    conn = client._connection = make_connection(resource)
+
+    ds_ref = DatasetReference(PROJECT, DS_ID)
+    before = Dataset(ds_ref)
+    before._properties["newAlphaProperty"] = "unreleased property"
+    after = client.create_dataset(before)
+
+    assert after.dataset_id == DS_ID
+    assert after.project == PROJECT
+    assert after._properties["newAlphaProperty"] == "unreleased property"
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path=path,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "newAlphaProperty": "unreleased property",
+            "labels": {},
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_client_location_wo_dataset_location(PROJECT, DS_ID, LOCATION):
+    PATH = "projects/%s/datasets" % PROJECT
+    RESOURCE = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "location": LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(RESOURCE)
+
+    ds_ref = DatasetReference(PROJECT, DS_ID)
+    before = Dataset(ds_ref)
+    after = client.create_dataset(before)
+
+    assert after.dataset_id == DS_ID
+    assert after.project == PROJECT
+    assert after.etag == RESOURCE["etag"]
+    assert after.full_dataset_id == RESOURCE["id"]
+    assert after.location == LOCATION
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path="/%s" % PATH,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+            "location": LOCATION,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_client_location_w_dataset_location(PROJECT, DS_ID, LOCATION):
+    PATH = "projects/%s/datasets" % PROJECT
+    OTHER_LOCATION = "EU"
+    RESOURCE = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "location": OTHER_LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(RESOURCE)
+
+    ds_ref = DatasetReference(PROJECT, DS_ID)
+    before = Dataset(ds_ref)
+    before.location = OTHER_LOCATION
+    after = client.create_dataset(before)
+
+    assert after.dataset_id == DS_ID
+    assert after.project == PROJECT
+    assert after.etag == RESOURCE["etag"]
+    assert after.full_dataset_id == RESOURCE["id"]
+    assert after.location == OTHER_LOCATION
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path="/%s" % PATH,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+            "location": OTHER_LOCATION,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_reference(PROJECT, DS_ID, LOCATION):
+    path = "/projects/%s/datasets" % PROJECT
+    resource = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "location": LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(resource)
+    dataset = client.create_dataset(DatasetReference(PROJECT, DS_ID))
+
+    assert dataset.dataset_id == DS_ID
+    assert dataset.project == PROJECT
+    assert dataset.etag == resource["etag"]
+    assert dataset.full_dataset_id == resource["id"]
+    assert dataset.location == LOCATION
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path=path,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+            "location": LOCATION,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_fully_qualified_string(PROJECT, DS_ID, LOCATION):
+    path = "/projects/%s/datasets" % PROJECT
+    resource = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "location": LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(resource)
+    dataset = client.create_dataset("{}.{}".format(PROJECT, DS_ID))
+
+    assert dataset.dataset_id == DS_ID
+    assert dataset.project == PROJECT
+    assert dataset.etag == resource["etag"]
+    assert dataset.full_dataset_id == resource["id"]
+    assert dataset.location == LOCATION
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path=path,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+            "location": LOCATION,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_w_string(PROJECT, DS_ID, LOCATION):
+    path = "/projects/%s/datasets" % PROJECT
+    resource = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "%s:%s" % (PROJECT, DS_ID),
+        "location": LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(resource)
+    with mock.patch(
+        "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+    ) as final_attributes:
+        dataset = client.create_dataset(DS_ID)
+
+    final_attributes.assert_called_once_with({"path": path}, client, None)
+
+    assert dataset.dataset_id == DS_ID
+    assert dataset.project == PROJECT
+    assert dataset.etag == resource["etag"]
+    assert dataset.full_dataset_id == resource["id"]
+    assert dataset.location == LOCATION
+
+    conn.api_request.assert_called_once_with(
+        method="POST",
+        path=path,
+        data={
+            "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+            "labels": {},
+            "location": LOCATION,
+        },
+        timeout=None,
+    )
+
+
+def test_create_dataset_alreadyexists_w_exists_ok_false(PROJECT, DS_ID, LOCATION):
+    client = make_client(location=LOCATION)
+    client._connection = make_connection(
+        google.api_core.exceptions.AlreadyExists("dataset already exists")
+    )
+
+    with pytest.raises(google.api_core.exceptions.AlreadyExists):
+        client.create_dataset(DS_ID)
+
+
+def test_create_dataset_alreadyexists_w_exists_ok_true(PROJECT, DS_ID, LOCATION):
+    post_path = "/projects/{}/datasets".format(PROJECT)
+    get_path = "/projects/{}/datasets/{}".format(PROJECT, DS_ID)
+    resource = {
+        "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+        "etag": "etag",
+        "id": "{}:{}".format(PROJECT, DS_ID),
+        "location": LOCATION,
+    }
+    client = make_client(location=LOCATION)
+    conn = client._connection = make_connection(
+        google.api_core.exceptions.AlreadyExists("dataset already exists"), resource
+    )
+    with mock.patch(
+        "google.cloud.bigquery.opentelemetry_tracing._get_final_span_attributes"
+    ) as final_attributes:
+        dataset = client.create_dataset(DS_ID, exists_ok=True)
+
+    final_attributes.assert_called_with({"path": get_path}, client, None)
+
+    assert dataset.dataset_id == DS_ID
+    assert dataset.project == PROJECT
+    assert dataset.etag == resource["etag"]
+    assert dataset.full_dataset_id == resource["id"]
+    assert dataset.location == LOCATION
+
+    conn.api_request.assert_has_calls(
+        [
+            mock.call(
+                method="POST",
+                path=post_path,
+                data={
+                    "datasetReference": {"projectId": PROJECT, "datasetId": DS_ID},
+                    "labels": {},
+                    "location": LOCATION,
+                },
+                timeout=None,
+            ),
+            mock.call(method="GET", path=get_path, timeout=None),
+        ]
+    )
diff --git a/tests/unit/test_delete_dataset.py b/tests/unit/test_delete_dataset.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_delete_dataset.py
@@ -0,0 +1,64 @@
+from .helpers import make_connection, make_client, dataset_polymorphic
+import google.api_core.exceptions
+import pytest
+
+
+@dataset_polymorphic
+def test_delete_dataset(make_dataset, get_reference, client, PROJECT, DS_ID):
+    dataset = make_dataset(PROJECT, DS_ID)
+    PATH = "projects/%s/datasets/%s" % (PROJECT, DS_ID)
+    conn = client._connection = make_connection({})
+    client.delete_dataset(dataset, timeout=7.5)
+    conn.api_request.assert_called_with(
+        method="DELETE", path="/%s" % PATH, query_params={}, timeout=7.5
+    )
+
+
+@dataset_polymorphic
+def test_delete_dataset_delete_contents(
+    make_dataset, get_reference, client, PROJECT, DS_ID
+):
+    PATH = "projects/%s/datasets/%s" % (PROJECT, DS_ID)
+    conn = client._connection = make_connection({})
+    dataset = make_dataset(PROJECT, DS_ID)
+    client.delete_dataset(dataset, delete_contents=True)
+    conn.api_request.assert_called_with(
+        method="DELETE",
+        path="/%s" % PATH,
+        query_params={"deleteContents": "true"},
+        timeout=None,
+    )
+
+
+def test_delete_dataset_wrong_type(client):
+    with pytest.raises(TypeError):
+        client.delete_dataset(42)
+
+
+def test_delete_dataset_w_not_found_ok_false(PROJECT, DS_ID):
+    path = "/projects/{}/datasets/{}".format(PROJECT, DS_ID)
+    http = object()
+    client = make_client(_http=http)
+    conn = client._connection = make_connection(
+        google.api_core.exceptions.NotFound("dataset not found")
+    )
+
+    with pytest.raises(google.api_core.exceptions.NotFound):
+        client.delete_dataset(DS_ID)
+
+    conn.api_request.assert_called_with(
+        method="DELETE", path=path, query_params={}, timeout=None
+    )
+
+
+def test_delete_dataset_w_not_found_ok_true(PROJECT, DS_ID):
+    path = "/projects/{}/datasets/{}".format(PROJECT, DS_ID)
+    http = object()
+    client = make_client(_http=http)
+    conn = client._connection = make_connection(
+        google.api_core.exceptions.NotFound("dataset not found")
+    )
+    client.delete_dataset(DS_ID, not_found_ok=True)
+    conn.api_request.assert_called_with(
+        method="DELETE", path=path, query_params={}, timeout=None
+    )
diff --git a/tests/unit/test_list_models.py b/tests/unit/test_list_models.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_list_models.py
@@ -0,0 +1,72 @@
+from .helpers import make_connection, dataset_polymorphic
+import pytest
+
+
+def test_list_models_empty_w_timeout(client, PROJECT, DS_ID):
+    path = "/projects/{}/datasets/{}/models".format(PROJECT, DS_ID)
+    conn = client._connection = make_connection({})
+
+    dataset_id = "{}.{}".format(PROJECT, DS_ID)
+    iterator = client.list_models(dataset_id, timeout=7.5)
+    page = next(iterator.pages)
+    models = list(page)
+    token = iterator.next_page_token
+
+    assert models == []
+    assert token is None
+    conn.api_request.assert_called_once_with(
+        method="GET", path=path, query_params={}, timeout=7.5
+    )
+
+
+@dataset_polymorphic
+def test_list_models_defaults(make_dataset, get_reference, client, PROJECT, DS_ID):
+    from google.cloud.bigquery.model import Model
+
+    MODEL_1 = "model_one"
+    MODEL_2 = "model_two"
+    PATH = "projects/%s/datasets/%s/models" % (PROJECT, DS_ID)
+    TOKEN = "TOKEN"
+    DATA = {
+        "nextPageToken": TOKEN,
+        "models": [
+            {
+                "modelReference": {
+                    "modelId": MODEL_1,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                }
+            },
+            {
+                "modelReference": {
+                    "modelId": MODEL_2,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                }
+            },
+        ],
+    }
+
+    conn = client._connection = make_connection(DATA)
+    dataset = make_dataset(PROJECT, DS_ID)
+
+    iterator = client.list_models(dataset)
+    assert iterator.dataset == get_reference(dataset)
+    page = next(iterator.pages)
+    models = list(page)
+    token = iterator.next_page_token
+
+    assert len(models) == len(DATA["models"])
+    for found, expected in zip(models, DATA["models"]):
+        assert isinstance(found, Model)
+        assert found.model_id == expected["modelReference"]["modelId"]
+    assert token == TOKEN
+
+    conn.api_request.assert_called_once_with(
+        method="GET", path="/%s" % PATH, query_params={}, timeout=None
+    )
+
+
+def test_list_models_wrong_type(client):
+    with pytest.raises(TypeError):
+        client.list_models(42)
diff --git a/tests/unit/test_list_routines.py b/tests/unit/test_list_routines.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_list_routines.py
@@ -0,0 +1,75 @@
+from .helpers import make_connection, dataset_polymorphic
+import pytest
+
+
+def test_list_routines_empty_w_timeout(client):
+    conn = client._connection = make_connection({})
+
+    iterator = client.list_routines("test-routines.test_routines", timeout=7.5)
+    page = next(iterator.pages)
+    routines = list(page)
+    token = iterator.next_page_token
+
+    assert routines == []
+    assert token is None
+    conn.api_request.assert_called_once_with(
+        method="GET",
+        path="/projects/test-routines/datasets/test_routines/routines",
+        query_params={},
+        timeout=7.5,
+    )
+
+
+@dataset_polymorphic
+def test_list_routines_defaults(make_dataset, get_reference, client, PROJECT):
+    from google.cloud.bigquery.routine import Routine
+
+    project_id = PROJECT
+    dataset_id = "test_routines"
+    path = f"/projects/{PROJECT}/datasets/test_routines/routines"
+    routine_1 = "routine_one"
+    routine_2 = "routine_two"
+    token = "TOKEN"
+    resource = {
+        "nextPageToken": token,
+        "routines": [
+            {
+                "routineReference": {
+                    "routineId": routine_1,
+                    "datasetId": dataset_id,
+                    "projectId": project_id,
+                }
+            },
+            {
+                "routineReference": {
+                    "routineId": routine_2,
+                    "datasetId": dataset_id,
+                    "projectId": project_id,
+                }
+            },
+        ],
+    }
+
+    conn = client._connection = make_connection(resource)
+    dataset = make_dataset(client.project, dataset_id)
+
+    iterator = client.list_routines(dataset)
+    assert iterator.dataset == get_reference(dataset)
+    page = next(iterator.pages)
+    routines = list(page)
+    actual_token = iterator.next_page_token
+
+    assert len(routines) == len(resource["routines"])
+    for found, expected in zip(routines, resource["routines"]):
+        assert isinstance(found, Routine)
+        assert found.routine_id == expected["routineReference"]["routineId"]
+    assert actual_token == token
+
+    conn.api_request.assert_called_once_with(
+        method="GET", path=path, query_params={}, timeout=None
+    )
+
+
+def test_list_routines_wrong_type(client):
+    with pytest.raises(TypeError):
+        client.list_routines(42)
diff --git a/tests/unit/test_list_tables.py b/tests/unit/test_list_tables.py
new file mode 100644
--- /dev/null
+++ b/tests/unit/test_list_tables.py
@@ -0,0 +1,145 @@
+from .helpers import make_connection, dataset_polymorphic
+import google.cloud.bigquery.dataset
+import pytest
+
+
+@dataset_polymorphic
+def test_list_tables_empty_w_timeout(
+    make_dataset, get_reference, client, PROJECT, DS_ID
+):
+    path = "/projects/{}/datasets/{}/tables".format(PROJECT, DS_ID)
+    conn = client._connection = make_connection({})
+
+    dataset = make_dataset(PROJECT, DS_ID)
+    iterator = client.list_tables(dataset, timeout=7.5)
+    assert iterator.dataset == get_reference(dataset)
+    page = next(iterator.pages)
+    tables = list(page)
+    token = iterator.next_page_token
+
+    assert tables == []
+    assert token is None
+    conn.api_request.assert_called_once_with(
+        method="GET", path=path, query_params={}, timeout=7.5
+    )
+
+
+@dataset_polymorphic
+def test_list_tables_defaults(make_dataset, get_reference, client, PROJECT, DS_ID):
+    from google.cloud.bigquery.table import TableListItem
+
+    TABLE_1 = "table_one"
+    TABLE_2 = "table_two"
+    PATH = "projects/%s/datasets/%s/tables" % (PROJECT, DS_ID)
+    TOKEN = "TOKEN"
+    DATA = {
+        "nextPageToken": TOKEN,
+        "tables": [
+            {
+                "kind": "bigquery#table",
+                "id": "%s:%s.%s" % (PROJECT, DS_ID, TABLE_1),
+                "tableReference": {
+                    "tableId": TABLE_1,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                },
+                "type": "TABLE",
+            },
+            {
+                "kind": "bigquery#table",
+                "id": "%s:%s.%s" % (PROJECT, DS_ID, TABLE_2),
+                "tableReference": {
+                    "tableId": TABLE_2,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                },
+                "type": "TABLE",
+            },
+        ],
+    }
+
+    conn = client._connection = make_connection(DATA)
+    dataset = make_dataset(PROJECT, DS_ID)
+
+    iterator = client.list_tables(dataset)
+    assert iterator.dataset == get_reference(dataset)
+    page = next(iterator.pages)
+    tables = list(page)
+    token = iterator.next_page_token
+
+    assert len(tables) == len(DATA["tables"])
+    for found, expected in zip(tables, DATA["tables"]):
+        assert isinstance(found, TableListItem)
+        assert found.full_table_id == expected["id"]
+        assert found.table_type == expected["type"]
+    assert token == TOKEN
+
+    conn.api_request.assert_called_once_with(
+        method="GET", path="/%s" % PATH, query_params={}, timeout=None
+    )
+
+
+def test_list_tables_explicit(client, PROJECT, DS_ID):
+    from google.cloud.bigquery.table import TableListItem
+
+    TABLE_1 = "table_one"
+    TABLE_2 = "table_two"
+    PATH = "projects/%s/datasets/%s/tables" % (PROJECT, DS_ID)
+    TOKEN = "TOKEN"
+    DATA = {
+        "tables": [
+            {
+                "kind": "bigquery#dataset",
+                "id": "%s:%s.%s" % (PROJECT, DS_ID, TABLE_1),
+                "tableReference": {
+                    "tableId": TABLE_1,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                },
+                "type": "TABLE",
+            },
+            {
+                "kind": "bigquery#dataset",
+                "id": "%s:%s.%s" % (PROJECT, DS_ID, TABLE_2),
+                "tableReference": {
+                    "tableId": TABLE_2,
+                    "datasetId": DS_ID,
+                    "projectId": PROJECT,
+                },
+                "type": "TABLE",
+            },
+        ]
+    }
+
+    conn = client._connection = make_connection(DATA)
+    dataset = google.cloud.bigquery.dataset.DatasetReference(PROJECT, DS_ID)
+
+    iterator = client.list_tables(
+        # Test with string for dataset ID.
+        DS_ID,
+        max_results=3,
+        page_token=TOKEN,
+    )
+    assert iterator.dataset == dataset
+    page = next(iterator.pages)
+    tables = list(page)
+    token = iterator.next_page_token
+
+    assert len(tables) == len(DATA["tables"])
+    for found, expected in zip(tables, DATA["tables"]):
+        assert isinstance(found, TableListItem)
+        assert found.full_table_id == expected["id"]
+        assert found.table_type == expected["type"]
+    assert token is None
+
+    conn.api_request.assert_called_once_with(
+        method="GET",
+        path="/%s" % PATH,
+        query_params={"maxResults": 3, "pageToken": TOKEN},
+        timeout=None,
+    )
+
+
+def test_list_tables_wrong_type(client):
+    with pytest.raises(TypeError):
+        client.list_tables(42)