christippett: Thought I'd help close a few other issues while I was at it. Added automatic generation of an ID when creating a new document (resolves #1).
mdowds: Hi @christippett , many thanks for the PR, and for taking on some of the issues others have raised! That all looks good to me, I'll get it merged.
diff --git a/mockfirestore/main.py b/mockfirestore/main.py
index b660af3..f028129 100644
--- a/mockfirestore/main.py
+++ b/mockfirestore/main.py
@@ -1,4 +1,6 @@
 import operator
+import random
+import string
 from collections import OrderedDict
 from functools import reduce
 from itertools import islice
@@ -28,11 +30,21 @@ class DocumentReference:
         self._data = data
         self._path = path
 
+    @property
+    def id(self):
+        return self._path[-1]
+
     def get(self) -> DocumentSnapshot:
         return DocumentSnapshot(get_by_path(self._data, self._path))
 
-    def set(self, data: Document):
-        set_by_path(self._data, self._path, data)
+    def delete(self):
+        delete_by_path(self._data, self._path)
+
+    def set(self, data: Dict, merge=False):
+        if merge:
+            self.update(data)
+        else:
+            set_by_path(self._data, self._path, data)
 
     def update(self, data: Dict[str, Any]):
         get_by_path(self._data, self._path).update(data)
@@ -86,8 +98,10 @@ class CollectionReference:
         self._data = data
         self._path = path
 
-    def document(self, name: str) -> DocumentReference:
+    def document(self, name: Optional[str] = None) -> DocumentReference:
         collection = get_by_path(self._data, self._path)
+        if name is None:
+            name = generate_random_string()
         new_path = self._path + [name]
         if name not in collection:
             set_by_path(self._data, new_path, {})
@@ -109,6 +123,12 @@ class CollectionReference:
         collection = get_by_path(self._data, self._path)
         return Query(collection).limit(limit_amount)
 
+    def list_documents(self, page_size: Optional[int] = None) -> Sequence[DocumentReference]:
+        docs = []
+        for key in get_by_path(self._data, self._path):
+            docs.append(self.document(key))
+        return docs
+
 
 class MockFirestore:
 
@@ -132,3 +152,12 @@ def get_by_path(data: Dict[str, T], path: Sequence[str]) -> T:
 def set_by_path(data: Dict[str, T], path: Sequence[str], value: T):
     """Set a value in a nested object in root by item sequence."""
     get_by_path(data, path[:-1])[path[-1]] = value
+
+
+def delete_by_path(data: Dict[str, T], path: Sequence[str]):
+    """Delete a value in a nested object in root by item sequence."""
+    del get_by_path(data, path[:-1])[path[-1]]
+
+
+def generate_random_string():
+    return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20))

Deleting documents
Hello again! 

I also noticed that the delete() function for `DocumentReference` wasn't added.

I added the following to `main.py` as a quick fix but would love to hear your thoughts:

```    
def delete(self):
    get_by_path(self._data, self._path).clear()
```
I also tried:
```    
def delete(self):
    self.set({})
```

They both seemed to have similar behavior and passed my unit tests
diff --git a/tests/test_collection_reference.py b/tests/test_collection_reference.py
index 0d23227..7e14e1f 100644
--- a/tests/test_collection_reference.py
+++ b/tests/test_collection_reference.py
@@ -1,6 +1,6 @@
 from unittest import TestCase
 
-from mockfirestore import MockFirestore
+from mockfirestore import MockFirestore, DocumentReference
 
 
 class TestCollectionReference(TestCase):
@@ -146,3 +146,15 @@ class TestCollectionReference(TestCase):
         docs = list(fs.collection('foo').order_by('order').limit(2).get())
         self.assertEqual({'order': 1}, docs[0].to_dict())
         self.assertEqual({'order': 2}, docs[1].to_dict())
+
+    def test_collection_listDocuments(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'order': 2},
+            'second': {'order': 1},
+            'third': {'order': 3}
+        }}
+        doc_refs = list(fs.collection('foo').list_documents())
+        self.assertEqual(3, len(doc_refs))
+        for doc_ref in doc_refs:
+            self.assertIsInstance(doc_ref, DocumentReference)
diff --git a/tests/test_document_reference.py b/tests/test_document_reference.py
index e1eecfc..3e5e7e5 100644
--- a/tests/test_document_reference.py
+++ b/tests/test_document_reference.py
@@ -12,6 +12,21 @@ class TestDocumentReference(TestCase):
         doc = fs.collection('foo').document('first').get().to_dict()
         self.assertEqual({'id': 1}, doc)
 
+    def test_document_get_documentIdEqualsKey(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'id': 1}
+        }}
+        doc_ref = fs.collection('foo').document('first')
+        self.assertEqual('first', doc_ref.id)
+
+    def test_document_get_newDocumentReturnsDefaultId(self):
+        fs = MockFirestore()
+        doc_ref = fs.collection('foo').document()
+        doc = doc_ref.get()
+        self.assertNotEqual(None, doc_ref.id)
+        self.assertFalse(doc.exists)
+
     def test_document_get_documentDoesNotExist(self):
         fs = MockFirestore()
         fs._data = {'foo': {}}
@@ -60,6 +75,24 @@ class TestDocumentReference(TestCase):
         doc = fs.collection('foo').document('bar').get().to_dict()
         self.assertEqual(doc_content, doc)
 
+    def test_document_set_mergeNewValue(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'id': 1}
+        }}
+        fs.collection('foo').document('first').set({'updated': True}, merge=True)
+        doc = fs.collection('foo').document('first').get().to_dict()
+        self.assertEqual({'id': 1, 'updated': True}, doc)
+
+    def test_document_set_overwriteValue(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'id': 1}
+        }}
+        fs.collection('foo').document('first').set({'new_id': 1}, merge=False)
+        doc = fs.collection('foo').document('first').get().to_dict()
+        self.assertEqual({'new_id': 1}, doc)
+
     def test_document_update_addNewValue(self):
         fs = MockFirestore()
         fs._data = {'foo': {
@@ -77,3 +110,12 @@ class TestDocumentReference(TestCase):
         fs.collection('foo').document('first').update({'id': 2})
         doc = fs.collection('foo').document('first').get().to_dict()
         self.assertEqual({'id': 2}, doc)
+
+    def test_document_delete_documentDoesNotExistAfterDelete(self):
+        fs = MockFirestore()
+        fs._data = {'foo': {
+            'first': {'id': 1}
+        }}
+        fs.collection('foo').document('first').delete()
+        doc = fs.collection('foo').document('first').get()
+        self.assertEqual(False, doc.exists)

pip install -e .
parse_log_pytest
pytest
pytest
3.7
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///croot/attrs_1668696182826/work
certifi @ file:///croot/certifi_1671487769961/work/certifi
flit_core @ file:///opt/conda/conda-bld/flit-core_1644941570762/work/source/flit_core
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1648562407465/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
-e git+https://github.com/mdowds/python-mock-firestore.git@590a1684c7c073879d74240685fe5a304afacfdd#egg=mock_firestore
packaging @ file:///croot/packaging_1671697413597/work
pluggy @ file:///tmp/build/80754af9/pluggy_1648042572264/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pytest==7.1.2
tomli @ file:///opt/conda/conda-bld/tomli_1657175507142/work
typing_extensions @ file:///croot/typing_extensions_1669924550328/work
zipp @ file:///croot/zipp_1672387121353/work

name: python-mock-firestore
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=22.1.0=py37h06a4308_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - flit-core=3.6.0=pyhd3eb1b0_0
  - importlib-metadata=4.11.3=py37h06a4308_0
  - importlib_metadata=4.11.3=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=22.0=py37h06a4308_0
  - pip=22.3.1=py37h06a4308_0
  - pluggy=1.0.0=py37h06a4308_1
  - py=1.11.0=pyhd3eb1b0_0
  - pytest=7.1.2=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tomli=2.0.1=py37h06a4308_0
  - typing_extensions=4.4.0=py37h06a4308_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.11.0=py37h06a4308_0
  - zlib=1.2.13=h5eee18b_1
prefix: /opt/conda/envs/python-mock-firestore

tests/test_collection_reference.py::TestCollectionReference::test_collection_listDocuments tests/test_document_reference.py::TestDocumentReference::test_document_delete_documentDoesNotExistAfterDelete tests/test_document_reference.py::TestDocumentReference::test_document_get_documentIdEqualsKey tests/test_document_reference.py::TestDocumentReference::test_document_get_newDocumentReturnsDefaultId tests/test_document_reference.py::TestDocumentReference::test_document_set_mergeNewValue tests/test_document_reference.py::TestDocumentReference::test_document_set_overwriteValue
tests/test_collection_reference.py::TestCollectionReference::test_collection_get_collectionDoesNotExist tests/test_collection_reference.py::TestCollectionReference::test_collection_get_nestedCollection tests/test_collection_reference.py::TestCollectionReference::test_collection_get_nestedCollection_collectionDoesNotExist tests/test_collection_reference.py::TestCollectionReference::test_collection_get_ordersByAscendingDocumentId_byDefault tests/test_collection_reference.py::TestCollectionReference::test_collection_get_returnsDocuments tests/test_collection_reference.py::TestCollectionReference::test_collection_limit tests/test_collection_reference.py::TestCollectionReference::test_collection_limitAndOrderBy tests/test_collection_reference.py::TestCollectionReference::test_collection_orderBy tests/test_collection_reference.py::TestCollectionReference::test_collection_orderBy_descending tests/test_collection_reference.py::TestCollectionReference::test_collection_whereEquals tests/test_collection_reference.py::TestCollectionReference::test_collection_whereGreaterThan tests/test_collection_reference.py::TestCollectionReference::test_collection_whereGreaterThanOrEqual tests/test_collection_reference.py::TestCollectionReference::test_collection_whereLessThan tests/test_collection_reference.py::TestCollectionReference::test_collection_whereLessThanOrEqual tests/test_document_reference.py::TestDocumentReference::test_document_get_documentDoesNotExist tests/test_document_reference.py::TestDocumentReference::test_document_get_returnsDocument tests/test_document_reference.py::TestDocumentReference::test_document_set_setsContentOfDocument tests/test_document_reference.py::TestDocumentReference::test_document_update_addNewValue tests/test_document_reference.py::TestDocumentReference::test_document_update_changeExistingValue tests/test_document_reference.py::TestDocumentReference::test_get_nestedDocument tests/test_document_reference.py::TestDocumentReference::test_get_nestedDocument_documentDoesNotExist
mockfirestore/main.py
mockfirestore/main.py