diff --git a/etl_manager/meta.py b/etl_manager/meta.py
index 446a955..9478bf4 100644
--- a/etl_manager/meta.py
+++ b/etl_manager/meta.py
@@ -50,6 +50,16 @@ class TableMeta :
 
         jsonschema.validate(self.to_dict(), _table_json_schema)
 
+    @property
+    def name(self) :
+        return self._name
+    
+    # Adding validation as Athena doesn't like names with dashes
+    @name.setter
+    def name(self, name) :
+        _validate_string(name)
+        self._name = name
+
     @property 
     def data_format(self) :
         return self._data_format
@@ -329,6 +339,16 @@ class DatabaseMeta :
         self.base_folder = base_folder
         self.description = description
 
+    @property
+    def name(self) :
+        return self._name
+    
+    # Adding validation as Athena doesn't like names with dashes
+    @name.setter
+    def name(self, name) :
+        _validate_string(name)
+        self._name = name
+
     @property
     def bucket(self):
         """
@@ -468,7 +488,7 @@ class DatabaseMeta :
 
         if write_tables :
             for t in self._tables :
-                t.write_to_json(folder_path + t.name + '.json')
+                t.write_to_json(os.path.join(folder_path, t.name + '.json'))
 
     def refresh_all_table_partitions(self):
         for table in self._tables:

write database not worknig
diff --git a/tests/test_tests.py b/tests/test_tests.py
index 74cddd7..83853ec 100644
--- a/tests/test_tests.py
+++ b/tests/test_tests.py
@@ -9,6 +9,8 @@ from etl_manager.meta import DatabaseMeta, TableMeta, read_database_folder, read
 from etl_manager.utils import _end_with_slash, _validate_string, _glue_client, read_json, _remove_final_slash
 from etl_manager.etl import GlueJob
 import boto3
+import tempfile
+import os
 
 class UtilsTest(unittest.TestCase) :
     """
@@ -96,7 +98,7 @@ class DatabaseMetaTest(unittest.TestCase):
         self.assertEqual(db.bucket, 'my-bucket')
         self.assertEqual(db.base_folder, 'database/database1')
 
-    def testread_json(self) :
+    def test_read_json(self) :
         db = read_database_folder('example/meta_data/db1/')
         self.assertEqual(db.name, 'workforce')
         self.assertEqual(db.description, 'Example database')
@@ -108,6 +110,29 @@ class DatabaseMetaTest(unittest.TestCase):
         db_dict = read_json('example/meta_data/db1/database.json')
         self.assertDictEqual(db_dict, db.to_dict())
 
+    def test_db_write_to_json(self) :
+        db = DatabaseMeta(name = 'workforce', bucket = 'my-bucket', base_folder = 'database/database1', description='Example database')
+        t = TableMeta(name = 'table1', location = 'somewhere')
+        db.add_table(t)
+
+        with tempfile.TemporaryDirectory() as tmpdirname:
+            db.write_to_json(tmpdirname)
+            dbr = read_json(os.path.join(tmpdirname, 'database.json'))
+            tr = read_json(os.path.join(tmpdirname, 'table1.json'))
+        
+        self.assertDictEqual(dbr, db.to_dict())
+        self.assertDictEqual(tr, t.to_dict())
+
+        with tempfile.TemporaryDirectory() as tmpdirname:
+            db.write_to_json(tmpdirname, write_tables=False)
+
+            dbr = read_json(os.path.join(tmpdirname, 'database.json'))
+            self.assertDictEqual(dbr, db.to_dict())
+
+            # Check that only db has been written
+            with self.assertRaises(FileNotFoundError) : 
+                tr = read_json(os.path.join(tmpdirname, 'table1.json'))
+
     def test_db_value_properties(self) :
         db = read_database_folder('example/meta_data/db1/')
         db.name = 'new_name'
@@ -129,6 +154,11 @@ class DatabaseMetaTest(unittest.TestCase):
         t = all(t in ['teams', 'employees', 'pay'] for t in db.table_names)
         self.assertTrue(t)
 
+    def test_db_name_validation(self) :
+        db = read_database_folder('example/meta_data/db1/')
+        with self.assertRaises(ValueError) : 
+            db.name = 'bad-name'
+
     def test_db_glue_name(self) :
         db = read_database_folder('example/meta_data/db1/')
         self.assertEqual(db.name, 'workforce')
@@ -143,16 +173,13 @@ class DatabaseMetaTest(unittest.TestCase):
     def test_db_table(self) :
         db = read_database_folder('example/meta_data/db1/')
         self.assertTrue(isinstance(db.table('employees'), TableMeta))
-        self.assertRaises(ValueError, db.table, 'not_a_table_name')
+        self.assertRaises(ValueError, db.table, 'not_a_table_object')
 
     def test_glue_specific_table(self):
         t = read_table_json("example/meta_data/db1/pay.json")
         glue_def = t.glue_table_definition("db_path")
         self.assertTrue(t.glue_table_definition("db_path")["Parameters"]['skip.header.line.count'] == '1')
 
-
-
-
     def test_add_remove_table(self) :
         db = read_database_folder('example/meta_data/db1/')
         self.assertRaises(ValueError, db.remove_table, 'not_a_table')
@@ -247,6 +274,11 @@ class TableMetaTest(unittest.TestCase):
         with self.assertRaises(ValueError) :
             tm2.database = 'not a database obj'
     
+    def test_db_name_validation(self) :
+        tm = TableMeta('test_name', location = 'folder/')
+        with self.assertRaises(ValueError) :
+            tm.name = 'bad-name'
+
     def test_column_operations(self) :
         kwargs = {
             "name": "employees",

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==25.3.0
boto3==1.37.23
botocore==1.37.23
-e git+https://github.com/moj-analytical-services/etl_manager.git@777d4f33f85bb5372fe5930a7084fec22e416dc3#egg=etl_manager
exceptiongroup==1.2.2
iniconfig==2.1.0
jmespath==1.0.1
jpype1==1.5.2
jsonschema==4.23.0
jsonschema-specifications==2024.10.1
packaging==24.2
pluggy==1.5.0
pyathenajdbc==3.0.1
pytest==8.3.5
python-dateutil==2.9.0.post0
referencing==0.36.2
rpds-py==0.24.0
s3transfer==0.11.4
six==1.17.0
tomli==2.2.1
typing_extensions==4.13.0
urllib3==1.26.20

name: etl_manager
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
  - ca-certificates=2025.2.25=h06a4308_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=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==25.3.0
      - boto3==1.37.23
      - botocore==1.37.23
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - jmespath==1.0.1
      - jpype1==1.5.2
      - jsonschema==4.23.0
      - jsonschema-specifications==2024.10.1
      - packaging==24.2
      - pluggy==1.5.0
      - pyathenajdbc==3.0.1
      - pytest==8.3.5
      - python-dateutil==2.9.0.post0
      - referencing==0.36.2
      - rpds-py==0.24.0
      - s3transfer==0.11.4
      - six==1.17.0
      - tomli==2.2.1
      - typing-extensions==4.13.0
      - urllib3==1.26.20
prefix: /opt/conda/envs/etl_manager

tests/test_tests.py::DatabaseMetaTest::test_db_name_validation tests/test_tests.py::DatabaseMetaTest::test_db_write_to_json tests/test_tests.py::TableMetaTest::test_db_name_validation
tests/test_tests.py::UtilsTest::test_meta_funs tests/test_tests.py::GlueTest::test_db_value_properties tests/test_tests.py::GlueTest::test_init tests/test_tests.py::TableTest::test_table_init tests/test_tests.py::DatabaseMetaTest::test_add_remove_table tests/test_tests.py::DatabaseMetaTest::test_db_glue_name tests/test_tests.py::DatabaseMetaTest::test_db_s3_database_path tests/test_tests.py::DatabaseMetaTest::test_db_table tests/test_tests.py::DatabaseMetaTest::test_db_table_names tests/test_tests.py::DatabaseMetaTest::test_db_to_dict tests/test_tests.py::DatabaseMetaTest::test_db_value_properties tests/test_tests.py::DatabaseMetaTest::test_glue_database_creation tests/test_tests.py::DatabaseMetaTest::test_glue_specific_table tests/test_tests.py::DatabaseMetaTest::test_init tests/test_tests.py::DatabaseMetaTest::test_location tests/test_tests.py::DatabaseMetaTest::test_read_json tests/test_tests.py::DatabaseMetaTest::test_table_to_dict tests/test_tests.py::TableMetaTest::test_column_operations tests/test_tests.py::TableMetaTest::test_null_init
etl_manager/meta.py
etl_manager/meta.py