-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunittest_reverse_complement.py
More file actions
76 lines (61 loc) · 3.56 KB
/
unittest_reverse_complement.py
File metadata and controls
76 lines (61 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import unittest
from test_utilities import generate_random_sequence, InvalidNucleotideError
# Import the function from the core file
from reverse_complement_generation import generate_reverse_complement
class TestReverseComplement(unittest.TestCase):
# Standard IUPAC degenerate complement map (used for expected values)
EXPECTED_COMPLEMENT_MAP = {
'A': 'T', 'T': 'A', 'G': 'C', 'C': 'G',
'R': 'Y', 'Y': 'R', 'S': 'S', 'W': 'W', 'K': 'M', 'M': 'K',
'H': 'D', 'D': 'H', 'V': 'B', 'B': 'V', 'N': 'N', 'X': 'X'
}
def test_standard_complement(self):
"""Tests basic ATGC complementation."""
self.assertEqual(generate_reverse_complement("ATGC", orientation="3'-5'"), "TACG")
def test_standard_reverse_complement(self):
"""Tests standard 5'-3' reverse complementation."""
# Standard DNA sequence
self.assertEqual(generate_reverse_complement("ATGC"), "GCAT")
self.assertEqual(generate_reverse_complement("AAACCCGGGTTT"), "AAACCCGGGTTT")
def test_degenerate_nucleotides(self):
"""Tests handling of all IUPAC degenerate codes (R, Y, S, W, K, M, H, D, V, B, N, X)."""
degenerate_seq = "ATGRYCSWKMDHVBNX"
# The complement: TAC YR GSWK M DHV B N X (reverse: XNB VHD M KWS GRYCAT)
expected_complement = "TACRYGSWKM DHVBNX"
expected_reverse_complement = "XNBVHDMKWSGRYCAT"
self.assertEqual(generate_reverse_complement(degenerate_seq, orientation="3'-5'"), expected_complement)
self.assertEqual(generate_reverse_complement(degenerate_seq, orientation="5'-3'"), expected_reverse_complement)
def test_edge_case_empty_sequence(self):
"""Tests an empty sequence (should return empty string)."""
self.assertEqual(generate_reverse_complement(""), "")
def test_edge_case_single_nucleotide(self):
"""Tests a single nucleotide (should return its complement)."""
self.assertEqual(generate_reverse_complement("A"), "T")
self.assertEqual(generate_reverse_complement("R"), "Y")
self.assertEqual(generate_reverse_complement("y", case_sensitive=True), "r") # Check degenerate case
def test_case_sensitivity(self):
"""Tests the optional case_sensitive parameter."""
# Non-case sensitive (default) should return all uppercase
self.assertEqual(generate_reverse_complement("atgc"), "GCAT")
# Case sensitive should maintain case
self.assertEqual(generate_reverse_complement("aTgc", case_sensitive=True), "gcAt")
def test_invalid_nucleotide_error(self):
"""Tests error handling for invalid characters."""
with self.assertRaises(InvalidNucleotideError):
generate_reverse_complement("ATGXLZ")
def test_invalid_orientation_error(self):
"""Tests error handling for invalid orientation strings."""
with self.assertRaises(ValueError):
generate_reverse_complement("ATGC", orientation="3'-6'")
def test_very_long_sequence(self):
"""Tests efficiency and correctness on a long random sequence."""
LONG_LEN = 100000
random_seq = generate_random_sequence(LONG_LEN)
rc = generate_reverse_complement(random_seq)
self.assertEqual(len(rc), LONG_LEN)
# Check that the first base of the RC is the complement of the last base of the original
last_base = random_seq[-1].upper()
first_rc_base = rc[0]
self.assertEqual(first_rc_base, self.EXPECTED_COMPLEMENT_MAP[last_base])
if __name__ == '__main__':
unittest.main()