1# This code is part of the Biopython distribution and governed by its 2# license. Please see the LICENSE file that should have been included 3# as part of this package. 4# 5 6"""Testing code for Restriction enzyme classes of Biopython.""" 7import unittest 8 9from Bio.Restriction import Analysis, Restriction, RestrictionBatch 10from Bio.Restriction import CommOnly, NonComm, AllEnzymes 11from Bio.Restriction import ( 12 Acc65I, 13 Asp718I, 14 BamHI, 15 EcoRI, 16 EcoRV, 17 KpnI, 18 SmaI, 19 MluCI, 20 McrI, 21 NdeI, 22 BsmBI, 23 AanI, 24 EarI, 25 SnaI, 26 SphI, 27) 28from Bio.Restriction import FormattedSeq 29from Bio.Seq import Seq, MutableSeq 30from Bio import BiopythonWarning 31 32 33class SequenceTesting(unittest.TestCase): 34 """Tests for dealing with input.""" 35 36 def test_sequence_object(self): 37 """Test if sequence must be a Seq or MutableSeq object.""" 38 with self.assertRaises(TypeError): 39 seq = FormattedSeq("GATC") 40 seq = FormattedSeq(Seq("TAGC")) 41 seq = FormattedSeq(MutableSeq("AGTC")) 42 seq = FormattedSeq(seq) 43 with self.assertRaises(TypeError): 44 EcoRI.search("GATC") 45 EcoRI.search(Seq("ATGC")) 46 EcoRI.search(MutableSeq("TCAG")) 47 48 def test_non_iupac_letters(self): 49 """Test if non-IUPAC letters raise a TypeError.""" 50 with self.assertRaises(TypeError): 51 seq = FormattedSeq(Seq("GATCZ")) 52 53 def test_formatted_seq(self): 54 """Test several methods of FormattedSeq.""" 55 self.assertEqual( 56 str(FormattedSeq(Seq("GATC"))), "FormattedSeq(Seq('GATC'), linear=True)" 57 ) 58 self.assertNotEqual(FormattedSeq(Seq("GATC")), FormattedSeq(Seq("TAGC"))) 59 self.assertNotEqual(FormattedSeq(Seq("TAGC")), Seq("TAGC")) 60 self.assertEqual(FormattedSeq(Seq("ATGC")), FormattedSeq(Seq("ATGC"))) 61 linear_seq = FormattedSeq(Seq("T")) 62 self.assertTrue(linear_seq.is_linear()) 63 linear_seq.circularise() 64 self.assertFalse(linear_seq.is_linear()) 65 linear_seq.linearise() 66 circular_seq = linear_seq.to_circular() 67 self.assertFalse(circular_seq.is_linear()) 68 linear_seq = circular_seq.to_linear() 69 self.assertTrue(linear_seq.is_linear()) 70 71 72class SimpleEnzyme(unittest.TestCase): 73 """Tests for dealing with basic enzymes using the Restriction package.""" 74 75 def test_init(self): 76 """Check for error during __init__.""" 77 with self.assertRaises(ValueError) as ve: 78 Restriction.OneCut("bla-me", (Restriction.RestrictionType,), {}) 79 self.assertIn("hyphen", str(ve.exception)) 80 81 def setUp(self): 82 """Set up some sequences for later use.""" 83 base_seq = Seq("AAAA") 84 self.ecosite_seq = base_seq + Seq(EcoRI.site) + base_seq 85 self.smasite_seq = base_seq + Seq(SmaI.site) + base_seq 86 self.kpnsite_seq = base_seq + Seq(KpnI.site) + base_seq 87 88 def test_eco_cutting(self): 89 """Test basic cutting with EcoRI (5'overhang).""" 90 self.assertEqual(EcoRI.site, "GAATTC") 91 self.assertTrue(EcoRI.cut_once()) 92 self.assertFalse(EcoRI.is_blunt()) 93 self.assertTrue(EcoRI.is_5overhang()) 94 self.assertFalse(EcoRI.is_3overhang()) 95 self.assertEqual(EcoRI.overhang(), "5' overhang") 96 self.assertTrue(EcoRI.is_defined()) 97 self.assertFalse(EcoRI.is_ambiguous()) 98 self.assertFalse(EcoRI.is_unknown()) 99 self.assertTrue(EcoRI.is_palindromic()) 100 self.assertTrue(EcoRI.is_comm()) 101 self.assertIn("Life Technologies", EcoRI.supplier_list()) 102 self.assertEqual(EcoRI.elucidate(), "G^AATT_C") 103 self.assertEqual(EcoRI.search(self.ecosite_seq), [6]) 104 self.assertEqual(EcoRI.characteristic(), (1, -1, None, None, "GAATTC")) 105 106 parts = EcoRI.catalyse(self.ecosite_seq) 107 self.assertEqual(len(parts), 2) 108 self.assertEqual(str(parts[1]), "AATTCAAAA") 109 parts = EcoRI.catalyze(self.ecosite_seq) 110 self.assertEqual(len(parts), 2) 111 112 def test_kpn_cutting(self): 113 """Test basic cutting with KpnI (3'overhang).""" 114 self.assertTrue(KpnI.is_3overhang()) 115 self.assertFalse(KpnI.is_5overhang()) 116 self.assertFalse(KpnI.is_blunt()) 117 self.assertEqual(KpnI.overhang(), "3' overhang") 118 parts = KpnI.catalyse(self.kpnsite_seq) 119 self.assertEqual(len(parts), 2) 120 self.assertEqual( 121 KpnI.catalyse(self.kpnsite_seq), KpnI.catalyze(self.kpnsite_seq) 122 ) 123 124 def test_sma_cutting(self): 125 """Test basic cutting with SmaI (blunt cutter).""" 126 self.assertTrue(SmaI.is_blunt()) 127 self.assertFalse(SmaI.is_3overhang()) 128 self.assertFalse(SmaI.is_5overhang()) 129 self.assertEqual(SmaI.overhang(), "blunt") 130 parts = SmaI.catalyse(self.smasite_seq) 131 self.assertEqual(len(parts), 2) 132 self.assertEqual(str(parts[1]), "GGGAAAA") 133 parts = SmaI.catalyze(self.smasite_seq) 134 self.assertEqual(len(parts), 2) 135 136 def test_ear_cutting(self): 137 """Test basic cutting with EarI (ambiguous overhang).""" 138 self.assertFalse(EarI.is_palindromic()) 139 self.assertFalse(EarI.is_defined()) 140 self.assertTrue(EarI.is_ambiguous()) 141 self.assertFalse(EarI.is_unknown()) 142 self.assertEqual(EarI.elucidate(), "CTCTTCN^NNN_N") 143 144 def test_sna_cutting(self): 145 """Test basic cutting with SnaI (unknown).""" 146 self.assertEqual(SnaI.elucidate(), "? GTATAC ?") 147 self.assertFalse(SnaI.is_defined()) 148 self.assertFalse(SnaI.is_ambiguous()) 149 self.assertTrue(SnaI.is_unknown()) 150 self.assertFalse(SnaI.is_comm()) 151 self.assertIsNone(SnaI.suppliers()) 152 self.assertEqual(SnaI.supplier_list(), []) 153 with self.assertRaises(TypeError): 154 SnaI.buffers("no company") 155 156 def test_circular_sequences(self): 157 """Deal with cutting circular sequences.""" 158 parts = EcoRI.catalyse(self.ecosite_seq, linear=False) 159 self.assertEqual(len(parts), 1) 160 locations = EcoRI.search(parts[0], linear=False) 161 self.assertEqual(locations, [1]) 162 163 parts = KpnI.catalyse(self.kpnsite_seq, linear=False) 164 self.assertEqual(len(parts), 1) 165 locations = KpnI.search(parts[0], linear=False) 166 self.assertEqual(locations, [1]) 167 168 parts = SmaI.catalyse(self.smasite_seq, linear=False) 169 self.assertEqual(len(parts), 1) 170 locations = SmaI.search(parts[0], linear=False) 171 self.assertEqual(locations, [1]) 172 173 self.assertEqual( 174 EarI.search(FormattedSeq(Seq("CTCTTCAAAAA")), linear=False), [8] 175 ) 176 self.assertEqual( 177 SnaI.search(FormattedSeq(Seq("GTATACAAAAA")), linear=False), [1] 178 ) 179 180 def test_shortcuts(self): 181 """Check if '/' and '//' work as '.search' and '.catalyse'.""" 182 self.assertEqual(EcoRI / self.ecosite_seq, [6]) 183 self.assertEqual(self.ecosite_seq / EcoRI, [6]) 184 self.assertEqual(len(EcoRI // self.ecosite_seq), 2) 185 self.assertEqual(len(self.ecosite_seq // EcoRI), 2) 186 187 def test_cutting_border_positions(self): 188 """Check if cutting after first and penultimate position works.""" 189 # Use EarI, cuts as follows: CTCTTCN^NNN_N 190 seq = Seq("CTCTTCA") 191 self.assertEqual(EarI.search(seq), []) 192 seq += "A" 193 self.assertEqual(EarI.search(seq), [8]) 194 # Recognition site on reverse-complement strand 195 seq = Seq("AAAAGAAGAG") 196 self.assertEqual(EarI.search(seq), []) 197 seq = "A" + seq 198 self.assertEqual(EarI.search(seq), [2]) 199 200 def test_recognition_site_on_both_strands(self): 201 """Check if recognition sites on both strands are properly handled.""" 202 seq = Seq("CTCTTCGAAGAG") 203 self.assertEqual(EarI.search(seq), [3, 8]) 204 205 def test_overlapping_cut_sites(self): 206 """Check if overlapping recognition sites are properly handled.""" 207 seq = Seq("CATGCACGCATGCATGCACGC") 208 self.assertEqual(SphI.search(seq), [13, 17]) 209 210 211class EnzymeComparison(unittest.TestCase): 212 """Tests for comparing various enzymes.""" 213 214 def test_basic_isochizomers(self): 215 """Test to be sure isochizomer and neoschizomers are as expected.""" 216 self.assertEqual(Acc65I.isoschizomers(), [Asp718I, KpnI]) 217 self.assertEqual(Acc65I.elucidate(), "G^GTAC_C") 218 self.assertEqual(Asp718I.elucidate(), "G^GTAC_C") 219 self.assertEqual(KpnI.elucidate(), "G_GTAC^C") 220 self.assertTrue(Acc65I.is_isoschizomer(KpnI)) 221 self.assertFalse(Acc65I.is_equischizomer(KpnI)) 222 self.assertTrue(Acc65I.is_neoschizomer(KpnI)) 223 self.assertIn(Acc65I, Asp718I.equischizomers()) 224 self.assertIn(KpnI, Asp718I.neoschizomers()) 225 self.assertIn(KpnI, Acc65I.isoschizomers()) 226 227 def test_comparisons(self): 228 """Test comparison operators between different enzymes.""" 229 # Comparison of iso- and neoschizomers 230 self.assertEqual(Acc65I, Acc65I) 231 self.assertNotEqual(Acc65I, KpnI) 232 self.assertFalse(Acc65I == Asp718I) # noqa: A500 233 # self.assertNotEqual(Acc65I, Asp718I) it doesn't work as expected 234 self.assertFalse(Acc65I != Asp718I) # noqa: A500 235 self.assertNotEqual(Acc65I, EcoRI) 236 self.assertTrue(Acc65I >> KpnI) 237 self.assertFalse(Acc65I >> Asp718I) 238 239 # Compare length of recognition sites 240 self.assertFalse(EcoRI >= EcoRV) 241 self.assertGreaterEqual(EcoRV, EcoRI) 242 with self.assertRaises(NotImplementedError): 243 EcoRV >= 3 244 self.assertFalse(EcoRI > EcoRV) 245 self.assertGreater(EcoRV, EcoRI) 246 with self.assertRaises(NotImplementedError): 247 EcoRV > 3 248 self.assertLessEqual(EcoRI, EcoRV) 249 self.assertFalse(EcoRV <= EcoRI) 250 with self.assertRaises(NotImplementedError): 251 EcoRV <= 3 252 self.assertLess(EcoRI, EcoRV) 253 self.assertFalse(EcoRV < EcoRI) 254 with self.assertRaises(NotImplementedError): 255 EcoRV < 3 256 257 # Compare compatible overhangs 258 self.assertTrue(Acc65I % Asp718I) 259 self.assertTrue(Acc65I % Acc65I) 260 self.assertFalse(Acc65I % KpnI) 261 with self.assertRaises(TypeError): 262 Acc65I % "KpnI" 263 self.assertTrue(SmaI % EcoRV) 264 self.assertTrue(EarI % EarI) 265 self.assertIn(EcoRV, SmaI.compatible_end()) 266 self.assertIn(Acc65I, Asp718I.compatible_end()) 267 268 269class RestrictionBatchPrintTest(unittest.TestCase): 270 """Tests Restriction.Analysis printing functionality.""" 271 272 def createAnalysis(self, seq_str, batch_ary): 273 """Restriction.Analysis creation helper method.""" 274 rb = Restriction.RestrictionBatch(batch_ary) 275 seq = Seq(seq_str) 276 return Restriction.Analysis(rb, seq) 277 278 def assertAnalysisFormat(self, analysis, expected): 279 """Test make_format. 280 281 Test that the Restriction.Analysis make_format(print_that) matches 282 some string. 283 """ 284 dct = analysis.mapping 285 ls, nc = [], [] 286 for k, v in dct.items(): 287 if v: 288 ls.append((k, v)) 289 else: 290 nc.append(k) 291 result = analysis.make_format(ls, "", [], "") 292 self.assertEqual(result.replace(" ", ""), expected.replace(" ", "")) 293 294 def test_make_format_map1(self): 295 """Test that print_as('map'); print_that() correctly wraps round. 296 297 1. With no marker. 298 """ 299 analysis = self.createAnalysis( 300 "CCAGTCTATAATTCG" 301 + Restriction.BamHI.site 302 + "GCGGCATCATACTCGAATATCGCGTGATGATACGTAGTAATTACGCATG", 303 ["BamHI"], 304 ) 305 analysis.print_as("map") 306 expected = [ 307 " 17 BamHI", 308 " | ", 309 "CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAATATCGCGTGATGATACGTAGTA", 310 "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", 311 "GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTTATAGCGCACTACTATGCATCAT", 312 "1 60", 313 "", 314 "ATTACGCATG", 315 "||||||||||", 316 "TAATGCGTAC", 317 "61 70", 318 "", 319 "", 320 ] 321 self.assertAnalysisFormat(analysis, "\n".join(expected)) 322 323 def test_make_format_map2(self): 324 """Test that print_as('map'); print_that() correctly wraps round. 325 326 2. With marker. 327 """ 328 analysis = self.createAnalysis( 329 "CCAGTCTATAATTCG" 330 + Restriction.BamHI.site 331 + "GCGGCATCATACTCGA" 332 + Restriction.BamHI.site 333 + "ATATCGCGTGATGATA" 334 + Restriction.NdeI.site 335 + "CGTAGTAATTACGCATG", 336 ["NdeI", "EcoRI", "BamHI", "BsmBI"], 337 ) 338 analysis.print_as("map") 339 expected = [ 340 " 17 BamHI", 341 " | ", 342 " | 39 BamHI", 343 " | | ", 344 "CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAGGATCCATATCGCGTGATGATAC", 345 "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", 346 "GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTCCTAGGTATAGCGCACTACTATG", 347 "1 60", 348 "", 349 " 62 NdeI", 350 " | ", 351 "ATATGCGTAGTAATTACGCATG", 352 "||||||||||||||||||||||", 353 "TATACGCATCATTAATGCGTAC", 354 "61 82", 355 "", 356 "", 357 ] 358 self.assertAnalysisFormat(analysis, "\n".join(expected)) 359 360 def test_make_format_map3(self): 361 """Test that print_as('map'); print_that() correctly wraps round. 362 363 3. With marker restricted. 364 """ 365 analysis = self.createAnalysis( 366 "CCAGTCTATAATTCG" 367 + Restriction.BamHI.site 368 + "GCGGCATCATACTCGA" 369 + Restriction.BamHI.site 370 + "ATATCGCGTGATGATA" 371 + Restriction.EcoRV.site 372 + "CGTAGTAATTACGCATG", 373 ["NdeI", "EcoRI", "BamHI", "BsmBI"], 374 ) 375 analysis.print_as("map") 376 expected = [ 377 " 17 BamHI", 378 " | ", 379 " | 39 BamHI", 380 " | | ", 381 "CCAGTCTATAATTCGGGATCCGCGGCATCATACTCGAGGATCCATATCGCGTGATGATAG", 382 "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||", 383 "GGTCAGATATTAAGCCCTAGGCGCCGTAGTATGAGCTCCTAGGTATAGCGCACTACTATC", 384 "1 60", 385 "", 386 "ATATCCGTAGTAATTACGCATG", 387 "||||||||||||||||||||||", 388 "TATAGGCATCATTAATGCGTAC", 389 "61 82", 390 "", 391 "", 392 ] 393 self.assertAnalysisFormat(analysis, "\n".join(expected)) 394 395 def test_change(self): 396 """Test that change() changes something.""" 397 seq = Seq( 398 "CCAGTCTATAATTCG" 399 + BamHI.site 400 + "GCGGCATCATACTCGA" 401 + BamHI.site 402 + "ATATCGCGTGATGATA" 403 + EcoRV.site 404 + "CGTAGTAATTACGCATG" 405 ) 406 batch = NdeI + EcoRI + BamHI + BsmBI 407 analysis = Analysis(batch, seq) 408 self.assertEqual(analysis.full()[BamHI], [17, 39]) 409 batch = NdeI + EcoRI + BsmBI 410 seq += NdeI.site 411 analysis.change(sequence=seq) 412 analysis.change(rb=batch) 413 self.assertEqual(len(analysis.full()), 3) 414 self.assertEqual(analysis.full()[NdeI], [85]) 415 with self.assertRaises(AttributeError): 416 analysis.change(**{"NameWidth": 3, "KonsoleWidth": 40}) # Console 417 418 419class RestrictionBatches(unittest.TestCase): 420 """Tests for dealing with batches of restriction enzymes.""" 421 422 def test_creating_batch(self): 423 """Creating and modifying a restriction batch.""" 424 batch = RestrictionBatch() 425 self.assertEqual(batch.suppl_codes()["N"], "New England Biolabs") 426 self.assertTrue(batch.is_restriction(EcoRI)) 427 batch = RestrictionBatch([EcoRI]) 428 batch.add(KpnI) 429 batch += EcoRV 430 self.assertEqual(len(batch), 3) 431 self.assertEqual(batch.elements(), ["EcoRI", "EcoRV", "KpnI"]) 432 # Problem with Python 3, as sequence of list may be different: 433 # self.assertEqual(batch.as_string(), ['EcoRI', 'KpnI', 'EcoRV']) 434 self.assertIn("EcoRI", batch.as_string()) 435 436 # The usual way to test batch membership 437 self.assertIn(EcoRV, batch) 438 self.assertIn(EcoRI, batch) 439 self.assertIn(KpnI, batch) 440 self.assertNotIn(SmaI, batch) 441 # Syntax sugar for the above 442 self.assertIn("EcoRV", batch) 443 self.assertNotIn("SmaI", batch) 444 445 batch.get(EcoRV) 446 self.assertRaises(ValueError, batch.get, SmaI) 447 batch.get(SmaI, add=True) 448 self.assertEqual(len(batch), 4) 449 batch.remove(SmaI) 450 batch.remove(EcoRV) 451 self.assertEqual(len(batch), 2) 452 453 self.assertNotIn(EcoRV, batch) 454 self.assertNotIn("EcoRV", batch) 455 456 # Creating a batch by addition of restriction enzymes 457 new_batch = EcoRI + KpnI 458 self.assertEqual(batch, new_batch) 459 # or by addition of a batch with an enzyme 460 another_new_batch = new_batch + EcoRV 461 new_batch += EcoRV 462 self.assertEqual(another_new_batch, new_batch) 463 self.assertRaises(TypeError, EcoRI.__add__, 1) 464 465 # Create a batch with suppliers and other supplier related methods 466 # These tests may be 'update sensitive' since company names and 467 # products may change often... 468 batch = RestrictionBatch((), ("S")) # Sigma 469 self.assertEqual(batch.current_suppliers(), ["Sigma Chemical Corporation"]) 470 self.assertIn(EcoRI, batch) 471 self.assertNotIn(AanI, batch) 472 batch.add_supplier("B") # Life Technologies 473 self.assertIn(AanI, batch) 474 475 def test_batch_analysis(self): 476 """Sequence analysis with a restriction batch.""" 477 seq = Seq("AAAA" + EcoRV.site + "AAAA" + EcoRI.site + "AAAA") 478 batch = RestrictionBatch([EcoRV, EcoRI]) 479 480 hits = batch.search(seq) 481 self.assertEqual(hits[EcoRV], [8]) 482 self.assertEqual(hits[EcoRI], [16]) 483 484 def test_premade_batches(self): 485 """Test content of premade batches CommOnly, NoComm, AllEnzymes.""" 486 self.assertEqual(len(AllEnzymes), (len(CommOnly) + len(NonComm))) 487 self.assertTrue(len(AllEnzymes) > len(CommOnly) > len(NonComm)) 488 489 def test_search_premade_batches(self): 490 """Test search with pre-made batches CommOnly, NoComm, AllEnzymes.""" 491 seq = Seq("ACCCGAATTCAAAACTGACTGATCGATCGTCGACTG") 492 search = AllEnzymes.search(seq) 493 self.assertEqual(search[MluCI], [6]) 494 # Check if '/' operator works as 'search': 495 search = CommOnly / seq 496 self.assertEqual(search[MluCI], [6]) 497 # Also in reverse order: 498 search = seq / NonComm 499 self.assertEqual(search[McrI], [28]) 500 501 def test_analysis_restrictions(self): 502 """Test Fancier restriction analysis.""" 503 new_seq = Seq("TTCAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAA") 504 rb = RestrictionBatch([EcoRI, KpnI, EcoRV]) 505 ana = Analysis(rb, new_seq, linear=False) 506 # Output only the result for enzymes which cut blunt: 507 self.assertEqual(ana.blunt(), {EcoRV: []}) 508 self.assertEqual(ana.full(), {KpnI: [], EcoRV: [], EcoRI: [33]}) 509 # Output only the result for enzymes which have a site: 510 self.assertEqual(ana.with_sites(), {EcoRI: [33]}) 511 # Output only the enzymes which have no site: 512 self.assertEqual(ana.without_site(), {KpnI: [], EcoRV: []}) 513 self.assertEqual(ana.with_site_size([32]), {}) 514 # Output only enzymes which produce 5' overhangs 515 self.assertEqual(ana.overhang5(), {EcoRI: [33]}) 516 # Output only enzymes which produce 3' overhangs 517 self.assertEqual(ana.overhang3(), {KpnI: []}) 518 # Output only enzymes which produce defined ends 519 self.assertEqual(ana.defined(), {KpnI: [], EcoRV: [], EcoRI: [33]}) 520 # Output only enzymes hich cut N times 521 self.assertEqual(ana.with_N_sites(2), {}) 522 # The enzymes which cut between position x and y: 523 with self.assertRaises(TypeError): 524 ana.only_between("t", 20) 525 with self.assertRaises(TypeError): 526 ana.only_between(1, "t") 527 self.assertEqual(ana.only_between(1, 20), {}) 528 self.assertEqual(ana.only_between(20, 34), {EcoRI: [33]}) 529 # Mix start/end order: 530 self.assertEqual(ana.only_between(34, 20), {EcoRI: [33]}) 531 self.assertEqual(ana.only_outside(20, 34), {}) 532 with self.assertWarns(BiopythonWarning): 533 ana.with_name(["fake"]) 534 self.assertEqual(ana.with_name([EcoRI]), {EcoRI: [33]}) 535 self.assertEqual((ana._boundaries(1, 20)[:2]), (1, 20)) 536 # Reverse order: 537 self.assertEqual((ana._boundaries(20, 1)[:2]), (1, 20)) 538 # Fix negative start: 539 self.assertEqual((ana._boundaries(-1, 20)[:2]), (20, 33)) 540 # Fix negative end: 541 self.assertEqual((ana._boundaries(1, -1)[:2]), (1, 33)) 542 # Sites in- and outside of boundaries 543 new_seq = Seq("GAATTCAAAAAAGAATTC") 544 rb = RestrictionBatch([EcoRI]) 545 ana = Analysis(rb, new_seq) 546 # Cut at least inside 547 self.assertEqual(ana.between(1, 7), {EcoRI: [2, 14]}) 548 # Cut at least inside and report only inside site 549 self.assertEqual(ana.show_only_between(1, 7), {EcoRI: [2]}) 550 # Cut at least outside 551 self.assertEqual(ana.outside(1, 7), {EcoRI: [2, 14]}) 552 # Don't cut within 553 self.assertEqual(ana.do_not_cut(7, 12), {EcoRI: [2, 14]}) 554 555 556class TestPrintOutputs(unittest.TestCase): 557 """Class to test various print outputs.""" 558 559 import sys 560 from io import StringIO 561 562 def test_supplier(self): 563 """Test output of supplier list for different enzyme types.""" 564 out = self.StringIO() 565 self.sys.stdout = out 566 EcoRI.suppliers() 567 self.assertIn("Life Technologies", out.getvalue()) 568 self.assertIsNone(SnaI.suppliers()) 569 EcoRI.all_suppliers() # Independent of enzyme, list of all suppliers 570 self.assertIn("Agilent Technologies", out.getvalue()) 571 batch = EcoRI + SnaI 572 batch.show_codes() 573 self.assertIn("N = New England Biolabs", out.getvalue()) 574 self.sys.stdout = self.sys.__stdout__ 575 576 def test_print_that(self): 577 """Test print_that function.""" 578 out = self.StringIO() 579 self.sys.stdout = out 580 my_batch = EcoRI + SmaI + KpnI 581 my_seq = Seq("GAATTCCCGGGATATA") # EcoRI and SmaI sites 582 analysis = Analysis(my_batch, my_seq) 583 analysis.print_that(None, title="My sequence\n\n", s1="Non Cutters\n\n") 584 self.assertIn("My sequence", out.getvalue()) 585 self.assertIn("Non Cutters", out.getvalue()) 586 self.assertIn("2.", out.getvalue()) 587 self.sys.stdout = self.sys.__stdout__ 588 589 def test_str_method(self): 590 """Test __str__ and __repr__ outputs.""" 591 batch = EcoRI + SmaI + KpnI 592 self.assertEqual(str(batch), "EcoRI+KpnI+SmaI") 593 batch += Asp718I 594 batch += SnaI 595 self.assertEqual(str(batch), "Asp718I+EcoRI...SmaI+SnaI") 596 self.assertEqual( 597 repr(batch), 598 "RestrictionBatch(['Asp718I', 'EcoRI', 'KpnI', 'SmaI', 'SnaI'])", 599 ) 600 601 602if __name__ == "__main__": 603 runner = unittest.TextTestRunner(verbosity=2) 604 unittest.main(testRunner=runner) 605