Skip to content

Commit c0102b6

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

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

micall/tests/test_append_primers.py

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

0 commit comments

Comments
 (0)