refactor tests
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# This is a basic workflow to help you get started with Actions
|
||||
|
||||
name: CI
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '30 17 * * *'
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
tests:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 2.7
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install sakee
|
||||
pip install html-testRunner
|
||||
|
||||
- name: Run tests
|
||||
run: python test.py
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: report
|
||||
path: reports/report.html
|
||||
+8
-3
@@ -1207,8 +1207,13 @@ def server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=Tru
|
||||
checklinks_number = config.get_setting('checklinks_number')
|
||||
verifiedItemlist = servertools.check_list_links(verifiedItemlist, checklinks_number)
|
||||
|
||||
if AutoPlay and not 'downloads' in inspect.stack()[3][1] or not 'downloads' in inspect.stack()[3][1] or not inspect.stack()[4][1]:
|
||||
autoplay.start(verifiedItemlist, item)
|
||||
try:
|
||||
if AutoPlay and not 'downloads' in inspect.stack()[3][1] or not 'downloads' in inspect.stack()[3][1] or not inspect.stack()[4][1]:
|
||||
autoplay.start(verifiedItemlist, item)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
pass
|
||||
|
||||
if Videolibrary and item.contentChannel != 'videolibrary':
|
||||
videolibrary(verifiedItemlist, item)
|
||||
@@ -1247,7 +1252,7 @@ def log(*args):
|
||||
|
||||
|
||||
def channel_config(item, itemlist):
|
||||
from channelselector import get_thumb
|
||||
from channelselector import get_thumb
|
||||
itemlist.append(
|
||||
Item(channel='setting',
|
||||
action="channel_config",
|
||||
|
||||
@@ -13,7 +13,12 @@ PY3 = False
|
||||
if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int
|
||||
|
||||
loggeractive = (config.get_setting("debug") == True)
|
||||
|
||||
try:
|
||||
xbmc.KodiStub()
|
||||
testMode = True
|
||||
import cgi
|
||||
except:
|
||||
testMode = False
|
||||
|
||||
def log_enable(active):
|
||||
global loggeractive
|
||||
@@ -39,6 +44,9 @@ def encode_log(message=""):
|
||||
else:
|
||||
message = str(message)
|
||||
|
||||
if testMode:
|
||||
message = cgi.escape(message)
|
||||
|
||||
return message
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ else:
|
||||
import os, xbmc, xbmcgui, xbmcplugin
|
||||
from past.utils import old_div
|
||||
from channelselector import get_thumb
|
||||
from core import trakt_tools, scrapertools
|
||||
from core import scrapertools
|
||||
from core.item import Item
|
||||
from platformcode import logger, config
|
||||
|
||||
@@ -920,6 +920,7 @@ def set_player(item, xlistitem, mediaurl, view, strm, nfo_path=None, head_nfo=No
|
||||
# Reproduce
|
||||
xbmc_player.play(playlist, xlistitem)
|
||||
if config.get_setting('trakt_sync'):
|
||||
from core import trakt_tools
|
||||
trakt_tools.wait_for_update_trakt()
|
||||
|
||||
elif player_mode == 1:
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import HtmlTestRunner
|
||||
import parameterized
|
||||
|
||||
from platformcode import config
|
||||
from platformcode import config, logger
|
||||
|
||||
config.set_setting('tmdb_active', False)
|
||||
|
||||
@@ -105,124 +107,69 @@ chNumRis = {
|
||||
},
|
||||
}
|
||||
|
||||
servers = []
|
||||
channels = []
|
||||
|
||||
def getChannels():
|
||||
channel_list = channelselector.filterchannels("all")
|
||||
ret = []
|
||||
for chItem in channel_list:
|
||||
channel_list = channelselector.filterchannels("all")[:1]
|
||||
ret = []
|
||||
for chItem in channel_list:
|
||||
try:
|
||||
ch = chItem.channel
|
||||
if ch not in chBlackList:
|
||||
ret.append({'ch': ch})
|
||||
return ret
|
||||
module = __import__('channels.%s' % ch, fromlist=["channels.%s" % ch])
|
||||
hasChannelConfig = False
|
||||
mainlist = module.mainlist(Item())
|
||||
menuItemlist = {}
|
||||
serversFound = {}
|
||||
|
||||
for it in mainlist:
|
||||
print 'preparing ' + ch + ' -> ' + it.title
|
||||
serversFound[it.title] = []
|
||||
|
||||
from specials import news
|
||||
if it.action == 'channel_config':
|
||||
hasChannelConfig = True
|
||||
continue
|
||||
if it.action == 'search': # channel-specific
|
||||
continue
|
||||
itemlist = getattr(module, it.action)(it)
|
||||
menuItemlist[it.title] = itemlist
|
||||
|
||||
dictNewsChannels, any_active = news.get_channels_list()
|
||||
# some sites might have no link inside, but if all results are without servers, there's something wrong
|
||||
for resIt in itemlist:
|
||||
if hasattr(module, resIt.action):
|
||||
serversFound[it.title] = getattr(module, resIt.action)(resIt)
|
||||
else:
|
||||
serversFound[it.title] = [resIt]
|
||||
|
||||
servers_found = []
|
||||
|
||||
|
||||
def getServers():
|
||||
ret = []
|
||||
for srv in servers_found:
|
||||
ret.append({'item': srv})
|
||||
return ret
|
||||
|
||||
|
||||
@parameterized.parameterized_class(getChannels())
|
||||
class GenericChannelTest(unittest.TestCase):
|
||||
def __init__(self, *args):
|
||||
self.module = __import__('channels.%s' % self.ch, fromlist=["channels.%s" % self.ch])
|
||||
super(GenericChannelTest, self).__init__(*args)
|
||||
|
||||
def test_menuitems(self):
|
||||
hasChannelConfig = False
|
||||
mainlist = self.module.mainlist(Item())
|
||||
self.assertTrue(mainlist, 'channel ' + self.ch + ' has no menu')
|
||||
|
||||
for it in mainlist:
|
||||
print 'testing ' + self.ch + ' -> ' + it.title
|
||||
if it.action == 'channel_config':
|
||||
hasChannelConfig = True
|
||||
continue
|
||||
if it.action == 'search': # channel-specific
|
||||
continue
|
||||
itemlist = getattr(self.module, it.action)(it)
|
||||
self.assertTrue(itemlist, 'channel ' + self.ch + ' -> ' + it.title + ' is empty')
|
||||
if self.ch in chNumRis: # i know how much results should be
|
||||
for content in chNumRis[self.ch]:
|
||||
if content in it.title:
|
||||
risNum = len([i for i in itemlist if not i.nextPage]) # not count nextpage
|
||||
self.assertEqual(chNumRis[self.ch][content], risNum,
|
||||
'channel ' + self.ch + ' -> ' + it.title + ' returned wrong number of results')
|
||||
if serversFound[it.title]:
|
||||
servers.extend(
|
||||
{'name': srv.server.lower(), 'server': srv} for srv in serversFound[it.title] if srv.server)
|
||||
break
|
||||
|
||||
for resIt in itemlist:
|
||||
self.assertLess(len(resIt.fulltitle), 110,
|
||||
'channel ' + self.ch + ' -> ' + it.title + ' might contain wrong titles\n' + resIt.fulltitle)
|
||||
if resIt.url:
|
||||
self.assertIsInstance(resIt.url, str, 'channel ' + self.ch + ' -> ' + it.title + ' -> ' + resIt.title + ' contain non-string url')
|
||||
self.assertIsNotNone(re.match(validUrlRegex, resIt.url),
|
||||
'channel ' + self.ch + ' -> ' + it.title + ' -> ' + resIt.title + ' might contain wrong url\n' + resIt.url)
|
||||
if 'year' in resIt.infoLabels and resIt.infoLabels['year']:
|
||||
msgYear = 'channel ' + self.ch + ' -> ' + it.title + ' might contain wrong infolabels year\n' + str(
|
||||
resIt.infoLabels['year'])
|
||||
self.assert_(type(resIt.infoLabels['year']) is int or resIt.infoLabels['year'].isdigit(), msgYear)
|
||||
self.assert_(int(resIt.infoLabels['year']) > 1900 and int(resIt.infoLabels['year']) < 2100, msgYear)
|
||||
channels.append(
|
||||
{'ch': ch, 'hasChannelConfig': hasChannelConfig, 'mainlist': mainlist, 'menuItemlist': menuItemlist,
|
||||
'serversFound': serversFound, 'module': module})
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
if resIt.title == typo(config.get_localized_string(30992), 'color kod bold'): # next page
|
||||
nextPageItemlist = getattr(self.module, resIt.action)(resIt)
|
||||
self.assertTrue(nextPageItemlist,
|
||||
'channel ' + self.ch + ' -> ' + it.title + ' has nextpage not working')
|
||||
from specials import news
|
||||
dictNewsChannels, any_active = news.get_channels_list()
|
||||
|
||||
# some sites might have no link inside, but if all results are without servers, there's something wrong
|
||||
servers = []
|
||||
for resIt in itemlist:
|
||||
if hasattr(self.module, resIt.action):
|
||||
servers = getattr(self.module, resIt.action)(resIt)
|
||||
else:
|
||||
servers = [resIt]
|
||||
# only 1 server item for single server
|
||||
serverNames = []
|
||||
serversFinal = []
|
||||
for s in servers:
|
||||
if not s['name'] in serverNames:
|
||||
serverNames.append(s['name'])
|
||||
serversFinal.append(s)
|
||||
|
||||
if servers:
|
||||
break
|
||||
self.assertTrue(servers, 'channel ' + self.ch + ' -> ' + it.title + ' has no servers on all results')
|
||||
for server in servers:
|
||||
srv = server.server.lower()
|
||||
if not srv:
|
||||
continue
|
||||
module = __import__('servers.%s' % srv, fromlist=["servers.%s" % srv])
|
||||
page_url = server.url
|
||||
print 'testing ' + page_url
|
||||
self.assert_(hasattr(module, 'test_video_exists'), srv + ' has no test_video_exists')
|
||||
if module.test_video_exists(page_url)[0]:
|
||||
urls = module.get_video_url(page_url)
|
||||
server_parameters = servertools.get_server_parameters(srv)
|
||||
self.assertTrue(urls or server_parameters.get("premium"), srv + ' scraper did not return direct urls for ' + page_url)
|
||||
print urls
|
||||
for u in urls:
|
||||
spl = u[1].split('|')
|
||||
if len(spl) == 2:
|
||||
directUrl, headersUrl = spl
|
||||
else:
|
||||
directUrl, headersUrl = spl[0], ''
|
||||
headers = {}
|
||||
if headersUrl:
|
||||
for name in headersUrl.split('&'):
|
||||
h, v = name.split('=')
|
||||
h = str(h)
|
||||
headers[h] = str(v)
|
||||
print headers
|
||||
if 'magnet:?' in directUrl: # check of magnet links not supported
|
||||
continue
|
||||
page = downloadpage(directUrl, headers=headers, only_headers=True, use_requests=True)
|
||||
self.assertTrue(page.success, srv + ' scraper returned an invalid link')
|
||||
self.assertLess(page.code, 400, srv + ' scraper returned a ' + str(page.code) + ' link')
|
||||
contentType = page.headers['Content-Type']
|
||||
self.assert_(contentType.startswith('video') or 'mpegurl' in contentType or 'octet-stream' in contentType or 'dash+xml' in contentType,
|
||||
srv + ' scraper did not return valid url for link ' + page_url + '\nDirect url: ' + directUrl + '\nContent-Type: ' + contentType)
|
||||
|
||||
self.assertTrue(hasChannelConfig, 'channel ' + self.ch + ' has no channel config')
|
||||
@parameterized.parameterized_class(channels)
|
||||
class GenericChannelTest(unittest.TestCase):
|
||||
def test_mainlist(self):
|
||||
self.assertTrue(self.mainlist, 'channel ' + self.ch + ' has no mainlist')
|
||||
self.assertTrue(self.hasChannelConfig, 'channel ' + self.ch + ' has no channel config')
|
||||
|
||||
def test_newest(self):
|
||||
for cat in dictNewsChannels:
|
||||
@@ -233,5 +180,90 @@ class GenericChannelTest(unittest.TestCase):
|
||||
break
|
||||
|
||||
|
||||
@parameterized.parameterized_class(
|
||||
[{'ch': ch['ch'], 'title': title, 'itemlist': itemlist, 'serversFound': ch['serversFound'][title]} for ch in channels for
|
||||
title, itemlist in ch['menuItemlist'].items()])
|
||||
class GenericChannelMenuItemTest(unittest.TestCase):
|
||||
def test_menu(self):
|
||||
print 'testing ' + self.ch + ' --> ' + title
|
||||
self.assertTrue(itemlist, 'channel ' + self.ch + ' -> ' + title + ' is empty')
|
||||
self.assertTrue(self.serversFound,
|
||||
'channel ' + self.ch + ' -> ' + title + ' has no servers on all results')
|
||||
|
||||
if self.ch in chNumRis: # i know how much results should be
|
||||
for content in chNumRis[self.ch]:
|
||||
if content in title:
|
||||
risNum = len([i for i in itemlist if not i.nextPage]) # not count nextpage
|
||||
self.assertEqual(chNumRis[self.ch][content], risNum,
|
||||
'channel ' + self.ch + ' -> ' + title + ' returned wrong number of results')
|
||||
break
|
||||
|
||||
for resIt in itemlist:
|
||||
print resIt.title + ' -> ' + resIt.url
|
||||
self.assertLess(len(resIt.fulltitle), 110,
|
||||
'channel ' + self.ch + ' -> ' + title + ' might contain wrong titles\n' + resIt.fulltitle)
|
||||
if resIt.url:
|
||||
self.assertIsInstance(resIt.url, str,
|
||||
'channel ' + self.ch + ' -> ' + title + ' -> ' + resIt.title + ' contain non-string url')
|
||||
self.assertIsNotNone(re.match(validUrlRegex, resIt.url),
|
||||
'channel ' + self.ch + ' -> ' + title + ' -> ' + resIt.title + ' might contain wrong url\n' + resIt.url)
|
||||
if 'year' in resIt.infoLabels and resIt.infoLabels['year']:
|
||||
msgYear = 'channel ' + self.ch + ' -> ' + title + ' might contain wrong infolabels year\n' + str(
|
||||
resIt.infoLabels['year'])
|
||||
self.assert_(type(resIt.infoLabels['year']) is int or resIt.infoLabels['year'].isdigit(),
|
||||
msgYear)
|
||||
self.assert_(int(resIt.infoLabels['year']) > 1900 and int(resIt.infoLabels['year']) < 2100,
|
||||
msgYear)
|
||||
|
||||
if resIt.title == typo(config.get_localized_string(30992), 'color kod bold'): # next page
|
||||
nextPageItemlist = getattr(self.module, resIt.action)(resIt)
|
||||
self.assertTrue(nextPageItemlist,
|
||||
'channel ' + self.ch + ' -> ' + title + ' has nextpage not working')
|
||||
|
||||
print '\ntest passed'
|
||||
|
||||
|
||||
@parameterized.parameterized_class(serversFinal)
|
||||
class GenericServerTest(unittest.TestCase):
|
||||
def test_get_video_url(self):
|
||||
module = __import__('servers.%s' % self.name, fromlist=["servers.%s" % self.name])
|
||||
page_url = self.server.url
|
||||
print 'testing ' + page_url
|
||||
self.assert_(hasattr(module, 'test_video_exists'), self.name + ' has no test_video_exists')
|
||||
try:
|
||||
if module.test_video_exists(page_url)[0]:
|
||||
urls = module.get_video_url(page_url)
|
||||
server_parameters = servertools.get_server_parameters(self.name)
|
||||
self.assertTrue(urls or server_parameters.get("premium"),
|
||||
self.name + ' scraper did not return direct urls for ' + page_url)
|
||||
print urls
|
||||
for u in urls:
|
||||
spl = u[1].split('|')
|
||||
if len(spl) == 2:
|
||||
directUrl, headersUrl = spl
|
||||
else:
|
||||
directUrl, headersUrl = spl[0], ''
|
||||
headers = {}
|
||||
if headersUrl:
|
||||
for name in headersUrl.split('&'):
|
||||
h, v = name.split('=')
|
||||
h = str(h)
|
||||
headers[h] = str(v)
|
||||
print headers
|
||||
if 'magnet:?' in directUrl: # check of magnet links not supported
|
||||
continue
|
||||
page = downloadpage(directUrl, headers=headers, only_headers=True, use_requests=True)
|
||||
self.assertTrue(page.success, self.name + ' scraper returned an invalid link')
|
||||
self.assertLess(page.code, 400, self.name + ' scraper returned a ' + str(page.code) + ' link')
|
||||
contentType = page.headers['Content-Type']
|
||||
self.assert_(contentType.startswith(
|
||||
'video') or 'mpegurl' in contentType or 'octet-stream' in contentType or 'dash+xml' in contentType,
|
||||
self.name + ' scraper did not return valid url for link ' + page_url + '\nDirect url: ' + directUrl + '\nContent-Type: ' + contentType)
|
||||
except:
|
||||
import traceback
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(report_name='report', add_timestamp=False,
|
||||
combine_reports=True, report_title='KoD Test Suite'))
|
||||
|
||||
Reference in New Issue
Block a user