Skip to content

Commit 26bce33

Browse files
committed
Add tests for append_primers
1 parent 8a7855d commit 26bce33

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

micall/tests/test_append_primers.py

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
2+
import pytest
3+
from pathlib import Path
4+
from Bio import SeqIO
5+
from Bio.Seq import Seq
6+
from Bio.SeqRecord import SeqRecord
7+
8+
9+
# Import functions/classes from our module.
10+
# (Assuming the code is in a module named append_primers_module.py.)
11+
from micall.utils.append_primers import (
12+
append_primers_to_record,
13+
entry,
14+
parse_arguments,
15+
append_primers,
16+
UserError,
17+
DEFAULT_FORWARD_PRIMER,
18+
DEFAULT_REVERSE_PRIMER,
19+
)
20+
21+
22+
def test_append_primers_to_record():
23+
original_seq = "ATGCGT"
24+
record = SeqRecord(Seq(original_seq), id="test", description="dummy")
25+
fwd_primer = "AAA"
26+
rev_primer = "TTT"
27+
new_record = append_primers_to_record(record, fwd_primer, rev_primer)
28+
expected_seq = fwd_primer + original_seq + rev_primer
29+
assert str(new_record.seq) == expected_seq
30+
assert new_record.id == record.id
31+
assert new_record.description == record.description
32+
33+
34+
def test_parse_arguments_defaults():
35+
# simulate command-line arguments,
36+
# note that the first two arguments are input and output files.
37+
test_args = [
38+
"input.fa",
39+
"output.fa",
40+
]
41+
args = parse_arguments(test_args)
42+
# Check that default primers are set.
43+
assert args.input_fasta == Path("input.fa")
44+
assert args.output_fasta == Path("output.fa")
45+
assert args.forward_primer == DEFAULT_FORWARD_PRIMER
46+
assert args.reverse_primer == DEFAULT_REVERSE_PRIMER
47+
48+
49+
def test_parse_arguments_custom_primers():
50+
test_args = [
51+
"in.fa",
52+
"out.fa",
53+
"--forward-primer", "CUSTOMFWD",
54+
"--reverse-primer", "CUSTOMREV"
55+
]
56+
args = parse_arguments(test_args)
57+
assert args.forward_primer == "CUSTOMFWD"
58+
assert args.reverse_primer == "CUSTOMREV"
59+
60+
61+
@pytest.fixture
62+
def temp_fasta_file(tmp_path: Path) -> Path:
63+
# Create a temporary FASTA file with two records.
64+
fasta_path = tmp_path / "input.fa"
65+
records = [
66+
SeqRecord(Seq("ATGC"), id="rec1", description="first"),
67+
SeqRecord(Seq("GATTACA"), id="rec2", description="second"),
68+
]
69+
with fasta_path.open("w") as f:
70+
SeqIO.write(records, f, "fasta")
71+
return fasta_path
72+
73+
74+
def test_append_primers_default(temp_fasta_file: Path, tmp_path: Path):
75+
# Use default primers.
76+
output_path = tmp_path / "output.fa"
77+
append_primers(
78+
input=temp_fasta_file,
79+
output=output_path,
80+
forward_primer=DEFAULT_FORWARD_PRIMER,
81+
reverse_primer=DEFAULT_REVERSE_PRIMER,
82+
)
83+
# Now read back the output.
84+
records = list(SeqIO.parse(str(output_path), "fasta"))
85+
# Check that the primers were appended.
86+
for rec in records:
87+
# The record sequence should start with DEFAULT_FORWARD_PRIMER
88+
# and end with DEFAULT_REVERSE_PRIMER.
89+
seq_str = str(rec.seq)
90+
assert seq_str.startswith(DEFAULT_FORWARD_PRIMER)
91+
assert seq_str.endswith(DEFAULT_REVERSE_PRIMER)
92+
# The middle part should be the original sequence. For instance,
93+
# for rec1, the original sequence was "ATGC".
94+
# We can extract the original: sequence[len(forward): -len(reverse)]
95+
original_seq = seq_str[len(DEFAULT_FORWARD_PRIMER): -len(DEFAULT_REVERSE_PRIMER)]
96+
# Check that the original sequence exists in the input file.
97+
# Without building a dict from the input file, we can simply check that
98+
# the extracted sequence is one of the known ones.
99+
assert original_seq in {"ATGC", "GATTACA"}
100+
101+
102+
def test_append_primers_default_main(temp_fasta_file: Path,
103+
tmp_path: Path,
104+
monkeypatch):
105+
# Use default primers.
106+
output_path = tmp_path / "output.fa"
107+
108+
monkeypatch.setattr("sys.argv", ["append_primers.py",
109+
str(temp_fasta_file),
110+
str(output_path),
111+
])
112+
113+
with pytest.raises(SystemExit) as exinfo:
114+
entry()
115+
116+
ex: SystemExit = exinfo.value
117+
assert ex.code == 0
118+
119+
# Now read back the output.
120+
records = list(SeqIO.parse(str(output_path), "fasta"))
121+
# Check that the primers were appended.
122+
for rec in records:
123+
# The record sequence should start with DEFAULT_FORWARD_PRIMER
124+
# and end with DEFAULT_REVERSE_PRIMER.
125+
seq_str = str(rec.seq)
126+
assert seq_str.startswith(DEFAULT_FORWARD_PRIMER)
127+
assert seq_str.endswith(DEFAULT_REVERSE_PRIMER)
128+
# The middle part should be the original sequence. For instance,
129+
# for rec1, the original sequence was "ATGC".
130+
# We can extract the original: sequence[len(forward): -len(reverse)]
131+
original_seq = seq_str[len(DEFAULT_FORWARD_PRIMER): -len(DEFAULT_REVERSE_PRIMER)]
132+
# Check that the original sequence exists in the input file.
133+
# Without building a dict from the input file, we can simply check that
134+
# the extracted sequence is one of the known ones.
135+
assert original_seq in {"ATGC", "GATTACA"}
136+
137+
138+
def test_append_primers_custom(temp_fasta_file: Path, tmp_path: Path):
139+
output_path = tmp_path / "output_custom.fa"
140+
custom_fwd = "CUSTOMFWD"
141+
custom_rev = "CUSTOMREV"
142+
append_primers(
143+
input=temp_fasta_file,
144+
output=output_path,
145+
forward_primer=custom_fwd,
146+
reverse_primer=custom_rev,
147+
)
148+
records = list(SeqIO.parse(str(output_path), "fasta"))
149+
for rec in records:
150+
seq_str = str(rec.seq)
151+
assert seq_str.startswith(custom_fwd)
152+
assert seq_str.endswith(custom_rev)
153+
154+
155+
def test_append_primers_missing_input(tmp_path: Path):
156+
# Create a non-existent input file path.
157+
missing_file = tmp_path / "non_existent.fa"
158+
output_file = tmp_path / "output.fa"
159+
with pytest.raises(UserError):
160+
append_primers(
161+
input=missing_file,
162+
output=output_file,
163+
forward_primer=DEFAULT_FORWARD_PRIMER,
164+
reverse_primer=DEFAULT_REVERSE_PRIMER,
165+
)

0 commit comments

Comments
 (0)