#!/usr/bin/env python2 #encoding:utf-8 #author:dbr/Ben #project:tvdb_api #repository:http://github.com/dbr/tvdb_api #license:unlicense (http://unlicense.org/) """Unittests for tvdb_api """ import os,os.path import sys print sys.path import datetime import unittest # Force parent directory onto path #sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(os.path.abspath('../../tests')) import sickbeard from tvdb_api import Tvdb import tvdb_ui from tvdb_api import (tvdb_shownotfound, tvdb_seasonnotfound, tvdb_episodenotfound, tvdb_attributenotfound) from lib import xmltodict import lib class test_tvdb_basic(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_different_case(self): """Checks the auto-correction of show names is working. It should correct the weirdly capitalised 'sCruBs' to 'Scrubs' """ self.assertEquals(self.t['scrubs'][1][4]['episodename'], 'My Old Lady') self.assertEquals(self.t['sCruBs']['seriesname'], 'Scrubs') def test_spaces(self): """Checks shownames with spaces """ self.assertEquals(self.t['My Name Is Earl']['seriesname'], 'My Name Is Earl') self.assertEquals(self.t['My Name Is Earl'][1][4]['episodename'], 'Faked His Own Death') def test_numeric(self): """Checks numeric show names """ self.assertEquals(self.t['24'][2][20]['episodename'], 'Day 2: 3:00 A.M.-4:00 A.M.') self.assertEquals(self.t['24']['seriesname'], '24') def test_show_iter(self): """Iterating over a show returns each seasons """ self.assertEquals( len( [season for season in self.t['Life on Mars']] ), 2 ) def test_season_iter(self): """Iterating over a show returns episodes """ self.assertEquals( len( [episode for episode in self.t['Life on Mars'][1]] ), 8 ) def test_get_episode_overview(self): """Checks episode overview is retrieved correctly. """ self.assertEquals( self.t['Battlestar Galactica (2003)'][1][6]['overview'].startswith( 'When a new copy of Doral, a Cylon who had been previously'), True ) def test_get_parent(self): """Check accessing series from episode instance """ show = self.t['Battlestar Galactica (2003)'] season = show[1] episode = show[1][1] self.assertEquals( season.show, show ) self.assertEquals( episode.season, season ) self.assertEquals( episode.season.show, show ) def test_no_season(self): show = self.t['Katekyo Hitman Reborn'] print tvdb_api print show[1][1] class test_tvdb_errors(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_seasonnotfound(self): """Checks exception is thrown when season doesn't exist. """ self.assertRaises(tvdb_seasonnotfound, lambda:self.t['CNNNN'][10][1]) def test_shownotfound(self): """Checks exception is thrown when episode doesn't exist. """ self.assertRaises(tvdb_shownotfound, lambda:self.t['the fake show thingy']) def test_episodenotfound(self): """Checks exception is raised for non-existent episode """ self.assertRaises(tvdb_episodenotfound, lambda:self.t['Scrubs'][1][30]) def test_attributenamenotfound(self): """Checks exception is thrown for if an attribute isn't found. """ self.assertRaises(tvdb_attributenotfound, lambda:self.t['CNNNN'][1][6]['afakeattributething']) self.assertRaises(tvdb_attributenotfound, lambda:self.t['CNNNN']['afakeattributething']) class test_tvdb_search(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_search_len(self): """There should be only one result matching """ self.assertEquals(len(self.t['My Name Is Earl'].search('Faked His Own Death')), 1) def test_search_checkname(self): """Checks you can get the episode name of a search result """ self.assertEquals(self.t['Scrubs'].search('my first')[0]['episodename'], 'My First Day') self.assertEquals(self.t['My Name Is Earl'].search('Faked His Own Death')[0]['episodename'], 'Faked His Own Death') def test_search_multiresults(self): """Checks search can return multiple results """ self.assertEquals(len(self.t['Scrubs'].search('my first')) >= 3, True) def test_search_no_params_error(self): """Checks not supplying search info raises TypeError""" self.assertRaises( TypeError, lambda: self.t['Scrubs'].search() ) def test_search_season(self): """Checks the searching of a single season""" self.assertEquals( len(self.t['Scrubs'][1].search("First")), 3 ) def test_search_show(self): """Checks the searching of an entire show""" self.assertEquals( len(self.t['CNNNN'].search('CNNNN', key='episodename')), 3 ) def test_aired_on(self): """Tests airedOn show method""" sr = self.t['Scrubs'].airedOn(datetime.date(2001, 10, 2)) self.assertEquals(len(sr), 1) self.assertEquals(sr[0]['episodename'], u'My First Day') class test_tvdb_data(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_episode_data(self): """Check the firstaired value is retrieved """ self.assertEquals( self.t['lost']['firstaired'], '2004-09-22' ) class test_tvdb_misc(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_repr_show(self): """Check repr() of Season """ self.assertEquals( repr(self.t['CNNNN']), "" ) def test_repr_season(self): """Check repr() of Season """ self.assertEquals( repr(self.t['CNNNN'][1]), "" ) def test_repr_episode(self): """Check repr() of Episode """ self.assertEquals( repr(self.t['CNNNN'][1][1]), "" ) def test_have_all_languages(self): """Check valid_languages is up-to-date (compared to languages.xml) """ et = self.t._getetsrc( "http://thetvdb.com/api/%s/languages.xml" % ( self.t.config['apikey'] ) ) languages = [x.find("abbreviation").text for x in et.findall("Language")] self.assertEquals( sorted(languages), sorted(self.t.config['valid_languages']) ) class test_tvdb_languages(unittest.TestCase): def test_episode_name_french(self): """Check episode data is in French (language="fr") """ t = tvdb_api.Tvdb(cache = True, language = "fr") self.assertEquals( t['scrubs'][1][1]['episodename'], "Mon premier jour" ) self.assertTrue( t['scrubs']['overview'].startswith( u"J.D. est un jeune m\xe9decin qui d\xe9bute" ) ) def test_episode_name_spanish(self): """Check episode data is in Spanish (language="es") """ t = tvdb_api.Tvdb(cache = True, language = "es") self.assertEquals( t['scrubs'][1][1]['episodename'], "Mi Primer Dia" ) self.assertTrue( t['scrubs']['overview'].startswith( u'Scrubs es una divertida comedia' ) ) def test_multilanguage_selection(self): """Check selected language is used """ class SelectEnglishUI(tvdb_ui.BaseUI): def selectSeries(self, allSeries): return [x for x in allSeries if x['language'] == "en"][0] class SelectItalianUI(tvdb_ui.BaseUI): def selectSeries(self, allSeries): return [x for x in allSeries if x['language'] == "it"][0] t_en = tvdb_api.Tvdb( cache=True, custom_ui = SelectEnglishUI, language = "en") t_it = tvdb_api.Tvdb( cache=True, custom_ui = SelectItalianUI, language = "it") self.assertEquals( t_en['dexter'][1][2]['episodename'], "Crocodile" ) self.assertEquals( t_it['dexter'][1][2]['episodename'], "Lacrime di coccodrillo" ) class test_tvdb_unicode(unittest.TestCase): def test_search_in_chinese(self): """Check searching for show with language=zh returns Chinese seriesname """ t = tvdb_api.Tvdb(cache = True, language = "zh") show = t[u'T\xecnh Ng\u01b0\u1eddi Hi\u1ec7n \u0110\u1ea1i'] self.assertEquals( type(show), tvdb_api.Show ) self.assertEquals( show['seriesname'], u'T\xecnh Ng\u01b0\u1eddi Hi\u1ec7n \u0110\u1ea1i' ) def test_search_in_all_languages(self): """Check search_all_languages returns Chinese show, with language=en """ t = tvdb_api.Tvdb(cache = True, search_all_languages = True, language="en") show = t[u'T\xecnh Ng\u01b0\u1eddi Hi\u1ec7n \u0110\u1ea1i'] self.assertEquals( type(show), tvdb_api.Show ) self.assertEquals( show['seriesname'], u'Virtues Of Harmony II' ) class test_tvdb_banners(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = True) def test_have_banners(self): """Check banners at least one banner is found """ self.assertEquals( len(self.t['scrubs']['_banners']) > 0, True ) def test_banner_url(self): """Checks banner URLs start with http:// """ for banner_type, banner_data in self.t['scrubs']['_banners'].items(): for res, res_data in banner_data.items(): for bid, banner_info in res_data.items(): self.assertEquals( banner_info['_bannerpath'].startswith("http://"), True ) def test_episode_image(self): """Checks episode 'filename' image is fully qualified URL """ self.assertEquals( self.t['scrubs'][1][1]['filename'].startswith("http://"), True ) def test_show_artwork(self): """Checks various image URLs within season data are fully qualified """ for key in ['banner', 'fanart', 'poster']: self.assertEquals( self.t['scrubs'][key].startswith("http://"), True ) class test_tvdb_actors(unittest.TestCase): t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, actors = True) def test_actors_is_correct_datatype(self): """Check show/_actors key exists and is correct type""" self.assertTrue( isinstance( self.t['scrubs']['_actors'], tvdb_api.Actors ) ) def test_actors_has_actor(self): """Check show has at least one Actor """ self.assertTrue( isinstance( self.t['scrubs']['_actors'][0], tvdb_api.Actor ) ) def test_actor_has_name(self): """Check first actor has a name""" self.assertEquals( self.t['scrubs']['_actors'][0]['name'], "Zach Braff" ) def test_actor_image_corrected(self): """Check image URL is fully qualified """ for actor in self.t['scrubs']['_actors']: if actor['image'] is not None: # Actor's image can be None, it displays as the placeholder # image on thetvdb.com self.assertTrue( actor['image'].startswith("http://") ) class test_tvdb_doctest(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, banners = False) def test_doctest(self): """Check docstring examples works""" import doctest doctest.testmod(tvdb_api) class test_tvdb_custom_caching(unittest.TestCase): def test_true_false_string(self): """Tests setting cache to True/False/string Basic tests, only checking for errors """ tvdb_api.Tvdb(cache = True) tvdb_api.Tvdb(cache = False) tvdb_api.Tvdb(cache = "/tmp") def test_invalid_cache_option(self): """Tests setting cache to invalid value """ try: tvdb_api.Tvdb(cache = 2.3) except ValueError: pass else: self.fail("Expected ValueError from setting cache to float") def test_custom_urlopener(self): class UsedCustomOpener(Exception): pass import urllib2 class TestOpener(urllib2.BaseHandler): def default_open(self, request): print request.get_method() raise UsedCustomOpener("Something") custom_opener = urllib2.build_opener(TestOpener()) t = tvdb_api.Tvdb(cache = custom_opener) try: t['scrubs'] except UsedCustomOpener: pass else: self.fail("Did not use custom opener") class test_tvdb_by_id(unittest.TestCase): t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, actors = True) def test_actors_is_correct_datatype(self): """Check show/_actors key exists and is correct type""" self.assertEquals( self.t[76156]['seriesname'], 'Scrubs' ) class test_tvdb_zip(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, useZip = True) def test_get_series_from_zip(self): """ """ self.assertEquals(self.t['scrubs'][1][4]['episodename'], 'My Old Lady') self.assertEquals(self.t['sCruBs']['seriesname'], 'Scrubs') def test_spaces_from_zip(self): """Checks shownames with spaces """ self.assertEquals(self.t['My Name Is Earl']['seriesname'], 'My Name Is Earl') self.assertEquals(self.t['My Name Is Earl'][1][4]['episodename'], 'Faked His Own Death') class test_tvdb_show_ordering(unittest.TestCase): # Used to store the cached instance of Tvdb() t_dvd = None t_air = None def setUp(self): if self.t_dvd is None: self.t_dvd = tvdb_api.Tvdb(cache = True, useZip = True, dvdorder=True) if self.t_air is None: self.t_air = tvdb_api.Tvdb(cache = True, useZip = True) def test_ordering(self): """Test Tvdb.search method """ self.assertEquals(u'The Train Job', self.t_air['Firefly'][1][1]['episodename']) self.assertEquals(u'Serenity', self.t_dvd['Firefly'][1][1]['episodename']) self.assertEquals(u'The Cat & the Claw (Part 1)', self.t_air['Batman The Animated Series'][1][1]['episodename']) self.assertEquals(u'On Leather Wings', self.t_dvd['Batman The Animated Series'][1][1]['episodename']) class test_tvdb_show_search(unittest.TestCase): # Used to store the cached instance of Tvdb() t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, useZip = True) def test_search(self): """Test Tvdb.search method """ results = self.t.search("my name is earl") all_ids = [x['seriesid'] for x in results] self.assertTrue('75397' in all_ids) class test_tvdb_alt_names(unittest.TestCase): t = None def setUp(self): if self.t is None: self.__class__.t = tvdb_api.Tvdb(cache = True, actors = True) def test_1(self): """Tests basic access of series name alias """ results = self.t.search("Don't Trust the B---- in Apartment 23") series = results[0] self.assertTrue( 'Apartment 23' in series['aliasnames'] ) if __name__ == '__main__': runner = unittest.TextTestRunner(verbosity = 2) unittest.main(testRunner = runner)