From 767dfd1cd34b4310f77f767c963b23a74b56444c Mon Sep 17 00:00:00 2001
From: Michael Boniface <m.j.boniface@soton.ac.uk>
Date: Tue, 18 Feb 2025 17:49:41 +0000
Subject: [PATCH] added initial pytests for basic workflow

---
 phen.py                | 10 ++++-
 tests/test_acmc.py     | 92 ++++++++++++++++++++++++++++++++++++++++++
 tests/test_commands.py | 75 ----------------------------------
 3 files changed, 100 insertions(+), 77 deletions(-)
 create mode 100644 tests/test_acmc.py
 delete mode 100644 tests/test_commands.py

diff --git a/phen.py b/phen.py
index ddbd0bb..03dd22e 100644
--- a/phen.py
+++ b/phen.py
@@ -182,7 +182,7 @@ def init(phen_dir, remote_url):
 	repo.git.add(all=True)		
 	repo.index.commit("initialised the phen git repo.")			
 		
-	print(f"Phenotype initialised")
+	print(f"Phenotype initialised successfully")
 	
 def validate(phen_dir):
 	"""Validates the phenotype directory is a git repo with standard structure"""		
@@ -566,7 +566,7 @@ def map(phen_dir, target_code_type, translate=True, verify=True):
 	
 	print(f"Saved concept_sets to {str(concept_set_path.resolve())}")	
 	
-	print(f"Phenotype processing completed")
+	print(f"Phenotype processed successfully")
 
 def publish(phen_dir):
 	"""Publishes updates to the phenotype by commiting all changes to the repo directory"""		
@@ -626,6 +626,8 @@ def publish(phen_dir):
 	except AttributeError:
 		print("No remote named 'origin' found, local repo.")
 
+	print(f"Phenotype published successfully")
+
 def copy(phen_dir, target_dir, version=None):
 	"""Copys a phen repo at a specific tagged version into a target directory"""	
 
@@ -666,6 +668,8 @@ def copy(phen_dir, target_dir, version=None):
 	
 	print(f"Copied {phen_path} {repo.head.commit.hexsha[:7]} in {copy_path}")
 
+	print(f"Phenotype copied successfully")
+
 def diff(phen_dir, phen_old_dir):
 	"""Compare the differences between two versions of a phenotype"""	
 	
@@ -738,6 +742,8 @@ def diff(phen_dir, phen_old_dir):
 			report.write(f"- Changed concepts []\n\n")
 
 
+	print(f"Phenotypes diff'd successfully")
+
 # Here's the atlas code that needs to go into anotehr function
 #	if output_path == "atlas":
 #		vocab_id = summary_config["omop"]["vocabulary_id"]
diff --git a/tests/test_acmc.py b/tests/test_acmc.py
new file mode 100644
index 0000000..4dbcf9e
--- /dev/null
+++ b/tests/test_acmc.py
@@ -0,0 +1,92 @@
+import pytest
+import argparse
+import sys
+import shutil
+
+import trud
+import omop
+import phen
+import acmc
+from pathlib import Path
+
+@pytest.fixture
+def tmp_dir():
+	# Setup tmp directory
+	temp_dir = Path("./tests/tmp")
+	temp_dir.mkdir(parents=True, exist_ok=True)
+	
+	# Yield the directory path to the test function
+	yield temp_dir
+	
+	# Remove the directory after the test finishes
+	shutil.rmtree(temp_dir)
+
+def test_phen_init_local_default(tmp_dir, monkeypatch, capsys):
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "init"])
+	# Mock input() to return "yes" to the question about reinitialising the directory 
+	monkeypatch.setattr("builtins.input", lambda _: "y")
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype initialised successfully" in captured.out
+
+def test_phen_init_local_specified(tmp_dir, monkeypatch, capsys):
+	phen_path = tmp_dir / "phen"
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "init", "-d", str(phen_path.resolve())])
+	# Mock input() to return "yes" to the question about reinitialising the directory 
+	monkeypatch.setattr("builtins.input", lambda _: "y")
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype initialised successfully" in captured.out
+
+def test_phen_workflow(tmp_dir, monkeypatch, capsys):
+	phen_path = tmp_dir / "phen"
+	phen_path = phen_path.resolve()
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "init", "-d", str(phen_path.resolve())])
+	# Mock input() to return "yes" to the question about reinitialising the directory 
+	monkeypatch.setattr("builtins.input", lambda _: "y")
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype initialised successfully" in captured.out
+
+	# copy examples across
+	shutil.rmtree(phen_path / 'codes')
+	ex_path = Path('./examples').resolve()
+	for item in ex_path.iterdir():
+		source = ex_path / item.name
+		destination = phen_path / item.name
+		if source.is_dir():
+			shutil.copytree(source, destination)
+		else:
+			shutil.copy2(source, destination)
+	shutil.copy( phen_path / 'config1.json', phen_path / 'config.json')	
+
+	# validate phenotype
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "validate", "-d", str(phen_path.resolve())])
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype validated successfully" in captured.out
+
+	# map phenotype
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "map", "-d", str(phen_path.resolve()), "-t", "read2", "-tr", "-ve"])
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype processed successfully" in captured.out
+
+	# publish phenotype
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "publish", "-d", str(phen_path.resolve())])
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype published successfully" in captured.out	
+
+	# copy phenotype'
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "copy", "-d", str(phen_path.resolve()), "-td", str(tmp_dir.resolve()), "-v", "v1.0.3"])
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotype copied successfully" in captured.out
+
+	# diff phenotype
+	old_path = tmp_dir / "v1.0.3"
+	monkeypatch.setattr(sys, "argv", ["acmc.py", "phen", "diff", "-d", str(phen_path.resolve()), "-old", str(old_path.resolve())])
+	acmc.main()
+	captured = capsys.readouterr()
+	assert "Phenotypes diff'd successfully" in captured.out
diff --git a/tests/test_commands.py b/tests/test_commands.py
deleted file mode 100644
index 375241f..0000000
--- a/tests/test_commands.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import pytest
-import argparse
-from unittest.mock import patch, MagicMock
-
-import trud
-import omop
-import phen
-from pathlib import Path
-from acmc import trud_install, omop_install, omop_clear, omop_delete, phen_init, phen_validate, phen_map, phen_publish, phen_copy, phen_diff
-
-def test_trud_install():
-    with patch("trud.install") as mock_install:
-        args = argparse.Namespace(api_key="test_key")
-        trud_install(args)
-        mock_install.assert_called_once_with("test_key")
-
-def test_omop_install():
-    with patch("omop.install") as mock_install:
-        args = argparse.Namespace(omop_folder="/path/to/omop")
-        omop_install(args)
-        mock_install.assert_called_once_with(omop.OMOP_DB_PATH, "/path/to/omop")
-
-def test_omop_clear():
-    with patch("omop.clear") as mock_clear:
-        args = argparse.Namespace()
-        omop_clear(args)
-        mock_clear.assert_called_once_with(omop.OMOP_DB_PATH)
-
-def test_omop_delete():
-    with patch("omop.delete") as mock_delete:
-        args = argparse.Namespace()
-        omop_delete(args)
-        mock_delete.assert_called_once_with(omop.OMOP_DB_PATH)
-
-def test_phen_init():
-    with patch("phen.init") as mock_init:
-        args = argparse.Namespace(phen_dir="/path/to/phen")
-        phen_init(args)
-        mock_init.assert_called_once_with("/path/to/phen")
-
-def test_phen_validate():
-    with patch("phen.validate") as mock_validate:
-        args = argparse.Namespace(phen_dir="/path/to/phen")
-        phen_validate(args)
-        mock_validate.assert_called_once_with("/path/to/phen")
-
-def test_phen_map():
-    with patch("phen.map") as mock_map:
-        args = argparse.Namespace(phen_dir="/path/to/phen", target_coding="icd10_code", translate=True, verify=True)
-        phen_map(args)
-        mock_map.assert_called_once_with("/path/to/phen", "icd10_code", True, True)
-
-def test_phen_publish():
-    with patch("phen.publish") as mock_publish:
-        args = argparse.Namespace(phen_dir="/path/to/phen")
-        phen_publish(args)
-        mock_publish.assert_called_once_with("/path/to/phen")
-
-def test_phen_copy():
-    with patch("phen.copy") as mock_copy:
-        args = argparse.Namespace(phen_dir="/path/to/phen", target_dir="/path/to/target", version="1.0")
-        phen_copy(args)
-        mock_copy.assert_called_once_with("/path/to/phen", "/path/to/target", "1.0")
-
-def test_phen_diff():
-    with patch("phen.diff") as mock_diff:
-        args = argparse.Namespace(phen_dir="/path/to/phen", phen_dir_old="/path/to/old_phen")
-        phen_diff(args)
-        mock_diff.assert_called_once_with("/path/to/phen", "/path/to/old_phen")
-
-def test_phen_local():
-    with patch("phen.diff") as mock_diff:
-        args = argparse.Namespace(phen_dir="/path/to/phen", phen_dir_old="/path/to/old_phen")
-        phen_diff(args)
-        mock_diff.assert_called_once_with("/path/to/phen", "/path/to/old_phen")
-- 
GitLab