macaca web(4)

米西米西滴,吃過中午飯來一篇,話說,上回書說道macaca 測試web(3),參數驅動來搞,那么有小伙本又來給雷子來需求, 登錄模塊能不能給我給重新封裝一下嗎, 我說干嘛封裝,現在不挺好,于是乎,接著小伙伴說,封裝好我可以用的地方就可以直接調用,我想想是啊,于是乎,雷子說這不是問題,你有需求雷子我有思路,來來,不要說了,來來,封裝的代碼展示下,起名叫做login.py

from page import page_data 
def login(deriver,username,password):deriver.element_by_id(page_data['username']).send_keys(username)deriver.element_by_id(page_data['password']).send_keys(password)deriver.element_by_id(page_data['login']).click()

小伙伴們說你給我用用,我還不會用呢,那么來來,我給你上上代碼

from macaca import WebDriver
import time,ddt,BSTestRunner,unittest
from config import die_arp,server_url,login_data
from login import login
@ddt.ddt
class BokeyuanTest(unittest.TestCase):def setUp(self):self.deriver=WebDriver(die_arp,server_url)self.deriver.init()self.deriver.get('https://passport.cnblogs.com/user/signin')def tearDown(self):self.deriver.quit()@ddt.data(*login_data)def test_login(self,login_data):login(self.deriver,login_data['username'],login_data['username'])time.sleep(1)self.assertTrue(self.deriver.element_by_id(login_data['id']).text,login_data['assert'])
if __name__ == '__main__':suite = unittest.TestSuite()now = time.strftime('%Y-%m%d', time.localtime(time.time()))report_dir = r'%s.html' % nowsuite.addTests(unittest.TestLoader().loadTestsFromTestCase(BokeyuanTest))re_open = open(report_dir, 'wb')runner = BSTestRunner.BSTestRunner(stream=re_open, title='demo by macaca', description='測試結果')runner.run(suite)

有沒有感覺引用很簡單呢,是的 答案是肯定的,就是函數的調用,封裝,只要有思路了,思路打開了,那么一起還是問題嗎,不是問題,不用你回答,基于的搞定,一切都好辦,

又有小伙伴說,你給我運行運行下,我說那么開始吧

?

測試完畢了,

?

小伙伴說怎么有錯誤,其實沒有的,這里是我的參數的問題,可以忽略,這是我設計用例設計的,因為有些代碼會牽扯到個人的隱私嗎,

測試有bug也是正常,那么我們就是去解決就好。

這里呢,

?

什么,原來是我的斷言寫錯了,

?

什么,我這個馬虎 吧定位寫錯誤了,修改后可以正常運行了,

那么有小伙伴說了,你這個文件都放到一個目錄

?

是不是感覺很難看,感覺不舒服啊,

那么好吧,我再來給你,給你優化下,、

?

busines 可以業務邏輯的公共方法,

data 可以存放一下數據,

page 頁面操作相關的

testcase ?用例

testresult 測試結果

?util 公共方法,與業務無關的

run.py 運行文件

那么我們要把腳本呢進行調整了,

?

?

login.pyfrom page.page import page_data 
def login(deriver,username,password):deriver.element_by_id(page_data['username']).send_keys(username)deriver.element_by_id(page_data['password']).send_keys(password)deriver.element_by_id(page_data['login']).click()
conf.pydie_arp={'platformName':'Desktop','browserName':'electron'
}
server_url={'hostname':'localhost','post':3456
}
login_data=[
{'username':'北漂的','password':'li1213456','id':'tip_btn','assert':'該用戶不存在'},
{'username':'','password':'li123456','id':'tip_input1','assert':'請輸入登錄用戶名'},
{'username':'','password':'','id':'tip_input1','assert':'請輸入登錄用戶名'},
{'username':'','password':'li123456','id':'tip_input1','assert':'請輸入登錄用戶名'},
{'username':'北漂的雷子','password':'li123456','id':'tip_btn','assert':'用戶名或密碼錯誤'},
{'username':'北漂的雷子','password':'','id':'tip_input2','assert':'請輸入密碼'},
{'username':'北漂的雷子','password':'li123456','id':'feed_recent','assert':'最新動態'},]
page.pypage_data={'username':'input1','password':'input2','login':'signin',
}
testbokeyuan.pyfrom macaca import WebDriver
import time,ddt,unittest
from data.config import die_arp,server_url,login_data
from busines.login import login
@ddt.ddt
class BokeyuanTest(unittest.TestCase):def setUp(self):self.deriver=WebDriver(die_arp,server_url)self.deriver.init()self.deriver.get('https://passport.cnblogs.com/user/signin')def tearDown(self):self.deriver.quit()@ddt.data(*login_data)def test_login(self,login_data):login(self.deriver,login_data['username'],login_data['username'])time.sleep(1)self.assertTrue(self.deriver.element_by_id(login_data['id']).text,login_data['assert'])
run.pyfrom testcase.testbokeyuan import BokeyuanTest
from util import BSTestRunner
import os,unittest,time
if __name__ == '__main__':suite = unittest.TestSuite()now = time.strftime('%Y-%m%d', time.localtime(time.time()))basedir = os.path.abspath(os.path.dirname(__file__))file_dir = os.path.join(basedir, 'testresult')file=os.path.join(file_dir,(now+'.html'))suite.addTests(unittest.TestLoader().loadTestsFromTestCase(BokeyuanTest))re_open = open(file, 'wb')runner = BSTestRunner.BSTestRunner(stream=re_open, title='demo by macaca', description='測試結果')runner.run(suite)

寫完就是這么可以run了,思路很簡單,就是拆分,組合,包的調用,基礎的問題

run下一看看,

?

報告也出來了。

?

里面的報錯,可以參考上面的解決方案, 因為我電腦博客園訪問現在有問題,我自己都登錄不了了,只能用之前的瀏覽器記住的密碼,好坑爹啊,一會再解決。

需求有沒有解決,好不好看的。

數據驅動,數據與代碼完全分離,業務人員只需編寫config以及少量簡單代碼,目前,只有一個登錄功能,后續會加入進去。

有沒有感覺更進一步呢。

我們最大的希望就是

關鍵字驅動,業務邏輯與代碼完全分離,業務人員只需編寫excel表即可執行ui自動化測試

這些大家都要相信我們都可以實現的 后續都可以搞定,通過配置文件去解決這些問題。

一路向前,你會走的更遠。

web(4)到此結束,感謝大家的觀看,

本人github ?https://github.com/liwanlei ?歡迎star,fork

有很多小伙伴不知道我的測報告有啥,感覺很美觀,其實我也是用的開源的東西BSTestRunner 支持python3

具體代碼

"""
A TestRunner for use with the Python unit testing framework. It generates a HTML report to show the result at a glance.The simplest way to use this is to invoke its main method. E.g.import unittestimport BSTestRunner... define your tests ...if __name__ == '__main__':BSTestRunner.main()For more customization options, instantiates a BSTestRunner object.
BSTestRunner is a counterpart to unittest's TextTestRunner. E.g.# output to a filefp = file('my_report.html', 'wb')runner = BSTestRunner.BSTestRunner(stream=fp,title='My unit test',description='This demonstrates the report output by BSTestRunner.')# Use an external stylesheet.# See the Template_mixin class for more customizable optionsrunner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'# run the testrunner.run(my_test_suite)------------------------------------------------------------------------
Copyright (c) 2004-2007, Wai Yip Tung
Copyright (c) 2016, Eason Han
All rights reserved.Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:* Redistributions of source code must retain the above copyright notice,this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyrightnotice, this list of conditions and the following disclaimer in thedocumentation and/or other materials provided with the distribution.
* Neither the name Wai Yip Tung nor the names of its contributors may beused to endorse or promote products derived from this software withoutspecific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""__author__ = "Wai Yip Tung && Eason Han"
__version__ = "0.8.4""""
Change HistoryVersion 0.8.3
* Modify html style using bootstrap3.Version 0.8.3
* Prevent crash on class or module-level exceptions (Darren Wurf).Version 0.8.2
* Show output inline instead of popup window (Viorel Lupu).Version in 0.8.1
* Validated XHTML (Wolfgang Borgert).
* Added description of test classes and test cases.Version in 0.8.0
* Define Template_mixin class for customization.
* Workaround a IE 6 bug that it does not treat <script> block as CDATA.Version in 0.7.1
* Back port to Python 2.3 (Frank Horowitz).
* Fix missing scroll bars in detail log (Podi).
"""# TODO: color stderr
# TODO: simplify javascript using ,ore than 1 class in the class attribute?import datetime
from io import StringIO as StringIO
import sys
import time
import unittest
from xml.sax import saxutils# ------------------------------------------------------------------------
# The redirectors below are used to capture output during testing. Output
# sent to sys.stdout and sys.stderr are automatically captured. However
# in some cases sys.stdout is already cached before BSTestRunner is
# invoked (e.g. calling logging.basicConfig). In order to capture those
# output, use the redirectors for the cached stream.
#
# e.g.
#   >>> logging.basicConfig(stream=BSTestRunner.stdout_redirector)
#   >>>def to_unicode(s):return s# try:#     return unicode(s)# except UnicodeDecodeError:#     # s is non ascii byte string#     return s.decode('unicode_escape')class OutputRedirector(object):""" Wrapper to redirect stdout or stderr """def __init__(self, fp):self.fp = fpdef write(self, s):self.fp.write(s)def writelines(self, lines):lines = map(to_unicode, lines)self.fp.writelines(lines)def flush(self):self.fp.flush()stdout_redirector = OutputRedirector(sys.stdout)
stderr_redirector = OutputRedirector(sys.stderr)# ----------------------------------------------------------------------
# Templateclass Template_mixin(object):"""Define a HTML template for report customerization and generation.Overall structure of an HTML reportHTML+------------------------+|<html>                  ||  <head>                ||                        ||   STYLESHEET           ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||  </head>               ||                        ||  <body>                ||                        ||   HEADING              ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||   REPORT               ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||   ENDING               ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||  </body>               ||</html>                 |+------------------------+"""STATUS = {0: 'pass',1: 'fail',2: 'error',}DEFAULT_TITLE = 'Unit Test Report'DEFAULT_DESCRIPTION = ''# ------------------------------------------------------------------------# HTML Template
HTML_TMPL = r"""<!DOCTYPE html>
<html lang="zh-cn"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><title>%(title)s</title><meta name="generator" content="%(generator)s"/><link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">%(stylesheet)s<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --><!-- WARNING: Respond.js doesn't work if you view the page via file:// --><!--[if lt IE 9]><script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script><script src="http://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script><![endif]--></head>
<body>
<script language="javascript" type="text/javascript"><!--
output_list = Array();/* level - 0:Summary; 1:Failed; 2:All */
function showCase(level) {trs = document.getElementsByTagName("tr");for (var i = 0; i < trs.length; i++) {tr = trs[i];id = tr.id;if (id.substr(0,2) == 'ft') {if (level < 1) {tr.className = 'hiddenRow';}else {tr.className = '';}}if (id.substr(0,2) == 'pt') {if (level > 1) {tr.className = '';}else {tr.className = 'hiddenRow';}}}
}function showClassDetail(cid, count) {var id_list = Array(count);var toHide = 1;for (var i = 0; i < count; i++) {tid0 = 't' + cid.substr(1) + '.' + (i+1);tid = 'f' + tid0;tr = document.getElementById(tid);if (!tr) {tid = 'p' + tid0;tr = document.getElementById(tid);}id_list[i] = tid;if (tr.className) {toHide = 0;}}for (var i = 0; i < count; i++) {tid = id_list[i];if (toHide) {document.getElementById('div_'+tid).style.display = 'none'document.getElementById(tid).className = 'hiddenRow';}else {document.getElementById(tid).className = '';}}
}function showTestDetail(div_id){var details_div = document.getElementById(div_id)var displayState = details_div.style.display// alert(displayState)if (displayState != 'block' ) {displayState = 'block'details_div.style.display = 'block'}else {details_div.style.display = 'none'}
}function html_escape(s) {s = s.replace(/&/g,'&amp;');s = s.replace(/</g,'&lt;');s = s.replace(/>/g,'&gt;');return s;
}/* obsoleted by detail in <div>
function showOutput(id, name) {var w = window.open("", //urlname,"resizable,scrollbars,status,width=800,height=450");d = w.document;d.write("<pre>");d.write(html_escape(output_list[id]));d.write("\n");d.write("<a href='javascript:window.close()'>close</a>\n");d.write("</pre>\n");d.close();
}
*/
--></script><div class="container">%(heading)s%(report)s%(ending)s
</div></body>
</html>
"""# variables: (title, generator, stylesheet, heading, report, ending)# ------------------------------------------------------------------------# Stylesheet#
    # alternatively use a <link> for external style sheet, e.g.#   <link rel="stylesheet" href="$url" type="text/css">
STYLESHEET_TMPL = """
<style type="text/css" media="screen">/* -- css div popup ------------------------------------------------------------------------ */
.popup_window {display: none;position: relative;left: 0px;top: 0px;/*border: solid #627173 1px; */padding: 10px;background-color: #99CCFF;font-family: "Lucida Console", "Courier New", Courier, monospace;text-align: left;font-size: 10pt;width: 1200px;
}/* -- report ------------------------------------------------------------------------ */#show_detail_line .label {font-size: 85%;cursor: pointer;
}#show_detail_line {margin: 2em auto 1em auto;
}#total_row  { font-weight: bold; }
.hiddenRow  { display: none; }
.testcase   { margin-left: 2em; }</style>
"""# ------------------------------------------------------------------------# Heading#
HEADING_TMPL = """<div class='heading'>
<h1>%(title)s</h1>
%(parameters)s
<p class='description'>%(description)s</p>
</div>""" # variables: (title, parameters, description)
HEADING_ATTRIBUTE_TMPL = """<p><strong>%(name)s:</strong> %(value)s</p>
""" # variables: (name, value)# ------------------------------------------------------------------------# Report#
REPORT_TMPL = """
<p id='show_detail_line'>
<span class="label label-primary" οnclick="showCase(0)">Summary</span>
<span class="label label-danger" οnclick="showCase(1)">Failed</span>
<span class="label label-default" οnclick="showCase(2)">All</span>
</p>
<table id='result_table' class="table"><thead><tr id='header_row'><th>Test Group/Test case</td><th>Count</td><th>Pass</td><th>Fail</td><th>Error</td><th>View</td></tr></thead><tbody>%(test_list)s</tbody><tfoot><tr id='total_row'><td>Total</td><td>%(count)s</td><td class="text text-success">%(Pass)s</td><td class="text text-danger">%(fail)s</td><td class="text text-warning">%(error)s</td><td>&nbsp;</td></tr></tfoot>
</table>
""" # variables: (test_list, count, Pass, fail, error)
REPORT_CLASS_TMPL = r"""
<tr class='%(style)s'><td>%(desc)s</td><td>%(count)s</td><td>%(Pass)s</td><td>%(fail)s</td><td>%(error)s</td><td><a class="btn btn-xs btn-primary"href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
</tr>
""" # variables: (style, desc, count, Pass, fail, error, cid)
REPORT_TEST_WITH_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'><td class='%(style)s'><div class='testcase'>%(desc)s</div></td><td colspan='5' align='center'><!--css div popup start--><a class="popup_link btn btn-xs btn-default" οnfοcus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >%(status)s</a><div id='div_%(tid)s' class="popup_window"><div style='text-align: right;cursor:pointer'><a οnfοcus='this.blur();' οnclick="document.getElementById('div_%(tid)s').style.display = 'none' " >[x]</a></div><pre>%(script)s</pre></div><!--css div popup end--></td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_NO_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'><td class='%(style)s'><div class='testcase'>%(desc)s</div></td><td colspan='5' align='center'>%(status)s</td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_OUTPUT_TMPL = r"""
%(id)s: %(output)s
""" # variables: (id, output)# ------------------------------------------------------------------------# ENDING#
ENDING_TMPL = """<div id='ending'>&nbsp;</div>"""# -------------------- The end of the Template class -------------------
TestResult = unittest.TestResultclass _TestResult(TestResult):# note: _TestResult is a pure representation of results.# It lacks the output and reporting ability compares to unittest._TextTestResult.def __init__(self, verbosity=1):TestResult.__init__(self)self.outputBuffer = StringIO()self.stdout0 = Noneself.stderr0 = Noneself.success_count = 0self.failure_count = 0self.error_count = 0self.verbosity = verbosity# result is a list of result in 4 tuple# (#   result code (0: success; 1: fail; 2: error),#   TestCase object,#   Test output (byte string),#   stack trace,# )self.result = []def startTest(self, test):TestResult.startTest(self, test)# just one buffer for both stdout and stderr  更改self.outputBuffer = StringIO()stdout_redirector.fp = self.outputBufferstderr_redirector.fp = self.outputBufferself.stdout0 = sys.stdoutself.stderr0 = sys.stderrsys.stdout = stdout_redirectorsys.stderr = stderr_redirectordef complete_output(self):"""Disconnect output redirection and return buffer.Safe to call multiple times."""if self.stdout0:sys.stdout = self.stdout0sys.stderr = self.stderr0self.stdout0 = Noneself.stderr0 = Nonereturn self.outputBuffer.getvalue()def stopTest(self, test):# Usually one of addSuccess, addError or addFailure would have been called.# But there are some path in unittest that would bypass this.# We must disconnect stdout in stopTest(), which is guaranteed to be called.
        self.complete_output()def addSuccess(self, test):self.success_count += 1TestResult.addSuccess(self, test)output = self.complete_output()self.result.append((0, test, output, ''))if self.verbosity > 1:sys.stderr.write('ok ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('.')def addError(self, test, err):self.error_count += 1TestResult.addError(self, test, err)_, _exc_str = self.errors[-1]output = self.complete_output()self.result.append((2, test, output, _exc_str))if self.verbosity > 1:sys.stderr.write('E  ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('E')def addFailure(self, test, err):self.failure_count += 1TestResult.addFailure(self, test, err)_, _exc_str = self.failures[-1]output = self.complete_output()self.result.append((1, test, output, _exc_str))if self.verbosity > 1:sys.stderr.write('F  ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('F')class BSTestRunner(Template_mixin):""""""def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):self.stream = streamself.verbosity = verbosityif title is None:self.title = self.DEFAULT_TITLEelse:self.title = titleif description is None:self.description = self.DEFAULT_DESCRIPTIONelse:self.description = descriptionself.startTime = datetime.datetime.now()def run(self, test):"Run the given test case or test suite."result = _TestResult(self.verbosity)try:test(result)except TypeError:passself.stopTime = datetime.datetime.now()self.generateReport(test, result)print('\n測試耗時: %s' % (self.stopTime-self.startTime))return resultdef sortResult(self, result_list):# unittest does not seems to run in any particular order.# Here at least we want to group them together by class.rmap = {}classes = []for n,t,o,e in result_list:cls = t.__class__if not cls in rmap:rmap[cls] = []classes.append(cls)rmap[cls].append((n,t,o,e))r = [(cls, rmap[cls]) for cls in classes]return rdef getReportAttributes(self, result):"""Return report attributes as a list of (name, value).Override this to add custom attributes."""startTime = str(self.startTime)[:19]duration = str(self.stopTime - self.startTime)status = []if result.success_count: status.append('<span class="text text-success">Pass <strong>%s</strong></span>'    % result.success_count)if result.failure_count: status.append('<span class="text text-danger">Failure <strong>%s</strong></span>' % result.failure_count)if result.error_count:   status.append('<span class="text text-warning">Error <strong>%s</strong></span>'   % result.error_count  )if status:status = ' '.join(status)else:status = 'none'return [('Start Time', startTime),('Duration', duration),('Status', status),]def generateReport(self, test, result):report_attrs = self.getReportAttributes(result)generator = 'BSTestRunner %s' % __version__stylesheet = self._generate_stylesheet()heading = self._generate_heading(report_attrs)report = self._generate_report(result)ending = self._generate_ending()output = self.HTML_TMPL % dict(title = saxutils.escape(self.title),generator = generator,stylesheet = stylesheet,heading = heading,report = report,ending = ending,)self.stream.write(output.encode('utf-8'))def _generate_stylesheet(self):return self.STYLESHEET_TMPLdef _generate_heading(self, report_attrs):a_lines = []for name, value in report_attrs:line = self.HEADING_ATTRIBUTE_TMPL % dict(name = saxutils.escape(name),####更改# value = saxutils.escape(value),
value = value,)a_lines.append(line)heading = self.HEADING_TMPL % dict(title = saxutils.escape(self.title),parameters = ''.join(a_lines),description = saxutils.escape(self.description),)return headingdef _generate_report(self, result):rows = []sortedResult = self.sortResult(result.result)for cid, (cls, cls_results) in enumerate(sortedResult):# subtotal for a classnp = nf = ne = 0for n,t,o,e in cls_results:if n == 0: np += 1elif n == 1: nf += 1else: ne += 1# format class descriptionif cls.__module__ == "__main__":name = cls.__name__else:name = "%s.%s" % (cls.__module__, cls.__name__)doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""desc = doc and '%s: %s' % (name, doc) or namerow = self.REPORT_CLASS_TMPL % dict(style = ne > 0 and 'text text-warning' or nf > 0 and 'text text-danger' or 'text text-success',desc = desc,count = np+nf+ne,Pass = np,fail = nf,error = ne,cid = 'c%s' % (cid+1),)rows.append(row)for tid, (n,t,o,e) in enumerate(cls_results):self._generate_report_test(rows, cid, tid, n, t, o, e)report = self.REPORT_TMPL % dict(test_list = ''.join(rows),count = str(result.success_count+result.failure_count+result.error_count),Pass = str(result.success_count),fail = str(result.failure_count),error = str(result.error_count),)return reportdef _generate_report_test(self, rows, cid, tid, n, t, o, e):# e.g. 'pt1.1', 'ft1.1', etchas_output = bool(o or e)tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)name = t.id().split('.')[-1]doc = t.shortDescription() or ""desc = doc and ('%s: %s' % (name, doc)) or nametmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL# o and e should be byte string because they are collected from stdout and stderr?if isinstance(o,str):# TODO: some problem with 'string_escape': it escape \n and mess up formating# uo = unicode(o.encode('string_escape'))uo = oelse:uo = oif isinstance(e,str):# TODO: some problem with 'string_escape': it escape \n and mess up formating# ue = unicode(e.encode('string_escape'))ue = eelse:ue = escript = self.REPORT_TEST_OUTPUT_TMPL % dict(id = tid,output = saxutils.escape(uo+ue),)row = tmpl % dict(tid = tid,Class = (n == 0 and 'hiddenRow' or 'none'),# Class = (n == 0 and 'hiddenRow' or 'text text-success'),# style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),style = n == 2 and 'text text-warning' or (n == 1 and 'text text-danger' or 'text text-success'),desc = desc,script = script,status = self.STATUS[n],)rows.append(row)if not has_output:returndef _generate_ending(self):return self.ENDING_TMPL##############################################################################
# Facilities for running tests from the command line
############################################################################### Note: Reuse unittest.TestProgram to launch test. In the future we may
# build our own launcher to support more specific command line
# parameters like test title, CSS, etc.
class TestProgram(unittest.TestProgram):"""A variation of the unittest.TestProgram. Please refer to the baseclass for command line parameters."""def runTests(self):# Pick BSTestRunner as the default test runner.# base class's testRunner parameter is not useful because it means# we have to instantiate BSTestRunner before we know self.verbosity.if self.testRunner is None:self.testRunner = BSTestRunner(verbosity=self.verbosity)unittest.TestProgram.runTests(self)main = TestProgram##############################################################################
# Executing this module from the command line
##############################################################################if __name__ == "__main__":main(module=None)
View Code

還有一個HTMLTestRunner 支持python3

代碼如下?

"""
A TestRunner for use with the Python unit testing framework. It
generates a HTML report to show the result at a glance.The simplest way to use this is to invoke its main method. E.g.import unittestimport HTMLTestRunner... define your tests ...if __name__ == '__main__':HTMLTestRunner.main()For more customization options, instantiates a HTMLTestRunner object.
HTMLTestRunner is a counterpart to unittest's TextTestRunner. E.g.# output to a filefp = file('my_report.html', 'wb')runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='My unit test',description='This demonstrates the report output by HTMLTestRunner.')# Use an external stylesheet.# See the Template_mixin class for more customizable optionsrunner.STYLESHEET_TMPL = '<link rel="stylesheet" href="my_stylesheet.css" type="text/css">'# run the testrunner.run(my_test_suite)------------------------------------------------------------------------
Copyright (c) 2004-2007, Wai Yip Tung
All rights reserved.Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:* Redistributions of source code must retain the above copyright notice,this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyrightnotice, this list of conditions and the following disclaimer in thedocumentation and/or other materials provided with the distribution.
* Neither the name Wai Yip Tung nor the names of its contributors may beused to endorse or promote products derived from this software withoutspecific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""# URL: http://tungwaiyip.info/software/HTMLTestRunner.html__author__ = "Wai Yip Tung"
__version__ = "0.8.2""""
Change HistoryVersion 0.8.2
* Show output inline instead of popup window (Viorel Lupu).Version in 0.8.1
* Validated XHTML (Wolfgang Borgert).
* Added description of test classes and test cases.Version in 0.8.0
* Define Template_mixin class for customization.
* Workaround a IE 6 bug that it does not treat <script> block as CDATA.Version in 0.7.1
* Back port to Python 2.3 (Frank Horowitz).
* Fix missing scroll bars in detail log (Podi).
"""# TODO: color stderr
# TODO: simplify javascript using ,ore than 1 class in the class attribute?import datetime
import io
import sys
import time
import unittest
from xml.sax import saxutils# ------------------------------------------------------------------------
# The redirectors below are used to capture output during testing. Output
# sent to sys.stdout and sys.stderr are automatically captured. However
# in some cases sys.stdout is already cached before HTMLTestRunner is
# invoked (e.g. calling logging.basicConfig). In order to capture those
# output, use the redirectors for the cached stream.
#
# e.g.
#   >>> logging.basicConfig(stream=HTMLTestRunner.stdout_redirector)
#   >>>class OutputRedirector(object):""" Wrapper to redirect stdout or stderr """def __init__(self, fp):self.fp = fpdef write(self, s):self.fp.write(s)def writelines(self, lines):self.fp.writelines(lines)def flush(self):self.fp.flush()stdout_redirector = OutputRedirector(sys.stdout)
stderr_redirector = OutputRedirector(sys.stderr)# ----------------------------------------------------------------------
# Templateclass Template_mixin(object):"""Define a HTML template for report customerization and generation.Overall structure of an HTML reportHTML+------------------------+|<html>                  ||  <head>                ||                        ||   STYLESHEET           ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||  </head>               ||                        ||  <body>                ||                        ||   HEADING              ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||   REPORT               ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||   ENDING               ||   +----------------+   ||   |                |   ||   +----------------+   ||                        ||  </body>               ||</html>                 |+------------------------+"""STATUS = {0: 'pass',1: 'fail',2: 'error',}DEFAULT_TITLE = 'Unit Test Report'DEFAULT_DESCRIPTION = ''# ------------------------------------------------------------------------# HTML Template
HTML_TMPL = r"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>%(title)s</title><meta name="generator" content="%(generator)s"/><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>%(stylesheet)s
</head>
<body>
<script language="javascript" type="text/javascript"><!--
output_list = Array();/* level - 0:Summary; 1:Failed; 2:All */
function showCase(level) {trs = document.getElementsByTagName("tr");for (var i = 0; i < trs.length; i++) {tr = trs[i];id = tr.id;if (id.substr(0,2) == 'ft') {if (level < 1) {tr.className = 'hiddenRow';}else {tr.className = '';}}if (id.substr(0,2) == 'pt') {if (level > 1) {tr.className = '';}else {tr.className = 'hiddenRow';}}}
}function showClassDetail(cid, count) {var id_list = Array(count);var toHide = 1;for (var i = 0; i < count; i++) {tid0 = 't' + cid.substr(1) + '.' + (i+1);tid = 'f' + tid0;tr = document.getElementById(tid);if (!tr) {tid = 'p' + tid0;tr = document.getElementById(tid);}id_list[i] = tid;if (tr.className) {toHide = 0;}}for (var i = 0; i < count; i++) {tid = id_list[i];if (toHide) {document.getElementById('div_'+tid).style.display = 'none'document.getElementById(tid).className = 'hiddenRow';}else {document.getElementById(tid).className = '';}}
}function showTestDetail(div_id){var details_div = document.getElementById(div_id)var displayState = details_div.style.display// alert(displayState)if (displayState != 'block' ) {displayState = 'block'details_div.style.display = 'block'}else {details_div.style.display = 'none'}
}function html_escape(s) {s = s.replace(/&/g,'&amp;');s = s.replace(/</g,'&lt;');s = s.replace(/>/g,'&gt;');return s;
}/* obsoleted by detail in <div>
function showOutput(id, name) {var w = window.open("", //urlname,"resizable,scrollbars,status,width=800,height=450");d = w.document;d.write("<pre>");d.write(html_escape(output_list[id]));d.write("\n");d.write("<a href='javascript:window.close()'>close</a>\n");d.write("</pre>\n");d.close();
}
*/
--></script>%(heading)s
%(report)s
%(ending)s</body>
</html>
"""# variables: (title, generator, stylesheet, heading, report, ending)# ------------------------------------------------------------------------# Stylesheet#
    # alternatively use a <link> for external style sheet, e.g.#   <link rel="stylesheet" href="$url" type="text/css">
STYLESHEET_TMPL = """
<style type="text/css" media="screen">
body        { font-family: verdana, arial, helvetica, sans-serif; font-size: 80%; }
table       { font-size: 100%; }
pre         { }/* -- heading ---------------------------------------------------------------------- */
h1 {font-size: 16pt;color: gray;
}
.heading {margin-top: 0ex;margin-bottom: 1ex;
}.heading .attribute {margin-top: 1ex;margin-bottom: 0;
}.heading .description {margin-top: 4ex;margin-bottom: 6ex;
}/* -- css div popup ------------------------------------------------------------------------ */
a.popup_link {
}a.popup_link:hover {color: red;
}.popup_window {display: none;position: relative;left: 0px;top: 0px;/*border: solid #627173 1px; */padding: 10px;background-color: #E6E6D6;font-family: "Lucida Console", "Courier New", Courier, monospace;text-align: left;font-size: 8pt;width: 500px;
}}
/* -- report ------------------------------------------------------------------------ */
#show_detail_line {margin-top: 3ex;margin-bottom: 1ex;
}
#result_table {width: 80%;border-collapse: collapse;border: 1px solid #777;
}
#header_row {font-weight: bold;color: white;background-color: #777;
}
#result_table td {border: 1px solid #777;padding: 2px;
}
#total_row  { font-weight: bold; }
.passClass  { background-color: #6c6; }
.failClass  { background-color: #c60; }
.errorClass { background-color: #c00; }
.passCase   { color: #6c6; }
.failCase   { color: #c60; font-weight: bold; }
.errorCase  { color: #c00; font-weight: bold; }
.hiddenRow  { display: none; }
.testcase   { margin-left: 2em; }/* -- ending ---------------------------------------------------------------------- */
#ending {
}</style>
"""# ------------------------------------------------------------------------# Heading#
HEADING_TMPL = """<div class='heading'>
<h1>%(title)s</h1>
%(parameters)s
<p class='description'>%(description)s</p>
</div>""" # variables: (title, parameters, description)
HEADING_ATTRIBUTE_TMPL = """<p class='attribute'><strong>%(name)s:</strong> %(value)s</p>
""" # variables: (name, value)# ------------------------------------------------------------------------# Report#
REPORT_TMPL = """
<p id='show_detail_line'>顯示
<a href='javascript:showCase(0)'>總數</a>
<a href='javascript:showCase(1)'>失敗</a>
<a href='javascript:showCase(2)'>所有</a>
</p>
<table id='result_table'>
<colgroup>
<col align='left' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
<col align='right' />
</colgroup>
<tr id='header_row'><td>測試組/測試用例</td><td>數量</td><td>通過</td><td>失敗</td><td>錯誤</td><td>查看</td>
</tr>
%(test_list)s
<tr id='total_row'><td>總共</td><td>%(count)s</td><td>%(Pass)s</td><td>%(fail)s</td><td>%(error)s</td><td>&nbsp;</td>
</tr>
</table>
""" # variables: (test_list, count, Pass, fail, error)
REPORT_CLASS_TMPL = r"""
<tr class='%(style)s'><td>%(desc)s</td><td>%(count)s</td><td>%(Pass)s</td><td>%(fail)s</td><td>%(error)s</td><td><a href="javascript:showClassDetail('%(cid)s',%(count)s)">Detail</a></td>
</tr>
""" # variables: (style, desc, count, Pass, fail, error, cid)
REPORT_TEST_WITH_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'><td class='%(style)s'><div class='testcase'>%(desc)s</div></td><td colspan='5' align='center'><!--css div popup start--><a class="popup_link" οnfοcus='this.blur();' href="javascript:showTestDetail('div_%(tid)s')" >%(status)s</a><div id='div_%(tid)s' class="popup_window"><div style='text-align: right; color:red;cursor:pointer'><a οnfοcus='this.blur();' οnclick="document.getElementById('div_%(tid)s').style.display = 'none' " >[x]</a></div><pre>%(script)s</pre></div><!--css div popup end--></td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_NO_OUTPUT_TMPL = r"""
<tr id='%(tid)s' class='%(Class)s'><td class='%(style)s'><div class='testcase'>%(desc)s</div></td><td colspan='5' align='center'>%(status)s</td>
</tr>
""" # variables: (tid, Class, style, desc, status)
REPORT_TEST_OUTPUT_TMPL = r"""
%(id)s: %(output)s
""" # variables: (id, output)# ------------------------------------------------------------------------# ENDING#
ENDING_TMPL = """<div id='ending'>&nbsp;</div>"""# -------------------- The end of the Template class -------------------
TestResult = unittest.TestResultclass _TestResult(TestResult):# note: _TestResult is a pure representation of results.# It lacks the output and reporting ability compares to unittest._TextTestResult.def __init__(self, verbosity=1):TestResult.__init__(self)self.stdout0 = Noneself.stderr0 = Noneself.success_count = 0self.failure_count = 0self.error_count = 0self.verbosity = verbosity# result is a list of result in 4 tuple# (#   result code (0: success; 1: fail; 2: error),#   TestCase object,#   Test output (byte string),#   stack trace,# )self.result = []def startTest(self, test):TestResult.startTest(self, test)# just one buffer for both stdout and stderrself.outputBuffer = io.StringIO()stdout_redirector.fp = self.outputBufferstderr_redirector.fp = self.outputBufferself.stdout0 = sys.stdoutself.stderr0 = sys.stderrsys.stdout = stdout_redirectorsys.stderr = stderr_redirectordef complete_output(self):"""Disconnect output redirection and return buffer.Safe to call multiple times."""if self.stdout0:sys.stdout = self.stdout0sys.stderr = self.stderr0self.stdout0 = Noneself.stderr0 = Nonereturn self.outputBuffer.getvalue()def stopTest(self, test):# Usually one of addSuccess, addError or addFailure would have been called.# But there are some path in unittest that would bypass this.# We must disconnect stdout in stopTest(), which is guaranteed to be called.
        self.complete_output()def addSuccess(self, test):self.success_count += 1TestResult.addSuccess(self, test)output = self.complete_output()self.result.append((0, test, output, ''))if self.verbosity > 1:sys.stderr.write('ok ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('.')def addError(self, test, err):self.error_count += 1TestResult.addError(self, test, err)_, _exc_str = self.errors[-1]output = self.complete_output()self.result.append((2, test, output, _exc_str))if self.verbosity > 1:sys.stderr.write('E  ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('E')def addFailure(self, test, err):self.failure_count += 1TestResult.addFailure(self, test, err)_, _exc_str = self.failures[-1]output = self.complete_output()self.result.append((1, test, output, _exc_str))if self.verbosity > 1:sys.stderr.write('F  ')sys.stderr.write(str(test))sys.stderr.write('\n')else:sys.stderr.write('F')class HTMLTestRunner(Template_mixin):""""""def __init__(self, stream=sys.stdout, verbosity=1, title=None, description=None):self.stream = streamself.verbosity = verbosityif title is None:self.title = self.DEFAULT_TITLEelse:self.title = titleif description is None:self.description = self.DEFAULT_DESCRIPTIONelse:self.description = descriptionself.startTime = datetime.datetime.now()def run(self, test):"Run the given test case or test suite."result = _TestResult(self.verbosity)test(result)self.stopTime = datetime.datetime.now()self.generateReport(test, result)# print >> sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime))return resultdef sortResult(self, result_list):# unittest does not seems to run in any particular order.# Here at least we want to group them together by class.rmap = {}classes = []for n,t,o,e in result_list:cls = t.__class__if not cls in rmap:rmap[cls] = []classes.append(cls)rmap[cls].append((n,t,o,e))r = [(cls, rmap[cls]) for cls in classes]return rdef getReportAttributes(self, result):"""Return report attributes as a list of (name, value).Override this to add custom attributes."""startTime = str(self.startTime)[:19]duration = str(self.stopTime - self.startTime)status = []if result.success_count: status.append('Pass %s'    % result.success_count)if result.failure_count: status.append('Failure %s' % result.failure_count)if result.error_count:   status.append('Error %s'   % result.error_count  )if status:status = ' '.join(status)else:status = 'none'return [('開始時間', startTime),('耗時', duration),('結果', status),]def generateReport(self, test, result):report_attrs = self.getReportAttributes(result)generator = 'HTMLTestRunner %s' % __version__stylesheet = self._generate_stylesheet()heading = self._generate_heading(report_attrs)report = self._generate_report(result)ending = self._generate_ending()output = self.HTML_TMPL % dict(title = saxutils.escape(self.title),generator = generator,stylesheet = stylesheet,heading = heading,report = report,ending = ending,)self.stream.write(output.encode('utf8'))def _generate_stylesheet(self):return self.STYLESHEET_TMPLdef _generate_heading(self, report_attrs):a_lines = []for name, value in report_attrs:line = self.HEADING_ATTRIBUTE_TMPL % dict(name = saxutils.escape(name),value = saxutils.escape(value),)a_lines.append(line)heading = self.HEADING_TMPL % dict(title = saxutils.escape(self.title),parameters = ''.join(a_lines),description = saxutils.escape(self.description),)return headingdef _generate_report(self, result):rows = []sortedResult = self.sortResult(result.result)for cid, (cls, cls_results) in enumerate(sortedResult):# subtotal for a classnp = nf = ne = 0for n,t,o,e in cls_results:if n == 0: np += 1elif n == 1: nf += 1else: ne += 1# format class descriptionif cls.__module__ == "__main__":name = cls.__name__else:name = "%s.%s" % (cls.__module__, cls.__name__)doc = cls.__doc__ and cls.__doc__.split("\n")[0] or ""desc = doc and '%s: %s' % (name, doc) or namerow = self.REPORT_CLASS_TMPL % dict(style = ne > 0 and 'errorClass' or nf > 0 and 'failClass' or 'passClass',desc = desc,count = np+nf+ne,Pass = np,fail = nf,error = ne,cid = 'c%s' % (cid+1),)rows.append(row)for tid, (n,t,o,e) in enumerate(cls_results):self._generate_report_test(rows, cid, tid, n, t, o, e)report = self.REPORT_TMPL % dict(test_list = ''.join(rows),count = str(result.success_count+result.failure_count+result.error_count),Pass = str(result.success_count),fail = str(result.failure_count),error = str(result.error_count),)return reportdef _generate_report_test(self, rows, cid, tid, n, t, o, e):# e.g. 'pt1.1', 'ft1.1', etchas_output = bool(o or e)tid = (n == 0 and 'p' or 'f') + 't%s.%s' % (cid+1,tid+1)name = t.id().split('.')[-1]doc = t.shortDescription() or ""desc = doc and ('%s: %s' % (name, doc)) or nametmpl = has_output and self.REPORT_TEST_WITH_OUTPUT_TMPL or self.REPORT_TEST_NO_OUTPUT_TMPL# o and e should be byte string because they are collected from stdout and stderr?if isinstance(o,str):# TODO: some problem with 'string_escape': it escape \n and mess up formating# uo = unicode(o.encode('string_escape'))# uo = o.decode('latin-1')uo = eelse:uo = oif isinstance(e,str):# TODO: some problem with 'string_escape': it escape \n and mess up formating# ue = unicode(e.encode('string_escape'))# ue = e.decode('latin-1')ue = eelse:ue = escript = self.REPORT_TEST_OUTPUT_TMPL % dict(id = tid,output = saxutils.escape(str(uo)+ue),)row = tmpl % dict(tid = tid,Class = (n == 0 and 'hiddenRow' or 'none'),style = n == 2 and 'errorCase' or (n == 1 and 'failCase' or 'none'),desc = desc,script = script,status = self.STATUS[n],)rows.append(row)if not has_output:returndef _generate_ending(self):return self.ENDING_TMPL##############################################################################
# Facilities for running tests from the command line
############################################################################### Note: Reuse unittest.TestProgram to launch test. In the future we may
# build our own launcher to support more specific command line
# parameters like test title, CSS, etc.
class TestProgram(unittest.TestProgram):"""A variation of the unittest.TestProgram. Please refer to the baseclass for command line parameters."""def runTests(self):# Pick HTMLTestRunner as the default test runner.# base class's testRunner parameter is not useful because it means# we have to instantiate HTMLTestRunner before we know self.verbosity.if self.testRunner is None:self.testRunner = HTMLTestRunner(verbosity=self.verbosity)unittest.TestProgram.runTests(self)main = TestProgram##############################################################################
# Executing this module from the command line
##############################################################################if __name__ == "__main__":main(module=None)
View Code

?

轉載于:https://www.cnblogs.com/leiziv5/p/7489134.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391422.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391422.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391422.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux中安裝cx_Oracle

https://blog.csdn.net/w657395940/article/details/41144225 各種嘗試都&#xff0c;最后 pip install cx-Oracle 成功導入 轉載于:https://www.cnblogs.com/gcgc/p/11447583.html

rfm模型分析與客戶細分_如何使用基于RFM的細分來確定最佳客戶

rfm模型分析與客戶細分With some free time at hand in the midst of COVID-19 pandemic, I decided to do pro bono consulting work. I was helping a few e-commerce companies with analyzing their customer data. A common theme I encountered during this work was tha…

leetcode 208. 實現 Trie (前綴樹)

Trie&#xff08;發音類似 “try”&#xff09;或者說 前綴樹 是一種樹形數據結構&#xff0c;用于高效地存儲和檢索字符串數據集中的鍵。這一數據結構有相當多的應用情景&#xff0c;例如自動補完和拼寫檢查。 請你實現 Trie 類&#xff1a; Trie() 初始化前綴樹對象。 void…

那些年收藏的技術文章(一) CSDN篇

#Android ##Android基礎及相關機制 Android Context 上下文 你必須知道的一切 Android中子線程真的不能更新UI嗎&#xff1f; Android基礎和運行機制 Android任務和返回棧完全解析&#xff0c;細數那些你所不知道的細節 【凱子哥帶你學Framework】Activity啟動過程全解析 【凱子…

chrome json插件_如何使用此免費的Chrome擴展程序(或Firefox插件)獲取易于閱讀的JSON樹

chrome json插件JSON is a very popular file format. Sometimes we may have a JSON object inside a browser tab that we need to read and this can be difficult.JSON是一種非常流行的文件格式。 有時我們可能需要在瀏覽器選項卡中包含一個JSON對象&#xff0c;這很困難。…

test10

test10 轉載于:https://www.cnblogs.com/Forever77/p/11447638.html

數據倉庫項目分析_數據分析項目:倉庫庫存

數據倉庫項目分析The code for this project can be found at my GitHub.該項目的代碼可以在我的GitHub上找到 。 介紹 (Introduction) The goal of this project was to analyse historic stock/inventory data to decide how much stock of each item a retailer should hol…

leetcode 213. 打家劫舍 II(dp)

你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋&#xff0c;每間房內都藏有一定的現金。這個地方所有的房屋都 圍成一圈 &#xff0c;這意味著第一個房屋和最后一個房屋是緊挨著的。同時&#xff0c;相鄰的房屋裝有相互連通的防盜系統&#xff0c;如果兩間相鄰的房屋在同一…

HTTP緩存的深入介紹:Cache-Control和Vary

簡介-本文范圍 (Introduction - scope of the article) This series of articles deals with caching in the context of HTTP. When properly done, caching can increase the performance of your application by an order of magnitude. On the contrary, when overlooked o…

059——VUE中vue-router之路由嵌套在文章系統中的使用方法:

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>vue-router之路由嵌套在文章系統中的使用方法&#xff1a;</title><script src"vue.js"></script><script src"v…

web前端效率提升之瀏覽器與本地文件的映射-遁地龍卷風

1.chrome瀏覽器&#xff0c;機制是攔截url&#xff0c;      1.在瀏覽器Element中調節的css樣式可以直接同步到本地文件&#xff0c;反之亦然&#xff0c;瀏覽器會重新加載css&#xff0c;省去刷新   2.在source面板下對js的編輯可以同步到本地文件&#xff0c;反之亦然…

linux : 各個發行版中修改python27默認編碼為utf-8

該方法可解決robot報錯&#xff1a;ascii codec cant encode character u\xf1 in position 16: ordinal not in range(128) 在下面目錄中新增文件&#xff1a;sitecustomize.py 內容為 #codingutf-8 import sysreload(sys) sys.setdefaultencoding(utf8) 各個發行版放置位置&a…

歸因分析_歸因分析:如何衡量影響? (第2部分,共2部分)

歸因分析By Lisa Cohen, Ryan Bouchard, Jane Huang, Daniel Yehdego and Siddharth Kumar由 麗莎科恩 &#xff0c; 瑞安布沙爾 &#xff0c; 黃美珍 &#xff0c; 丹尼爾Yehdego 和 亞洲時報Siddharth庫馬爾 介紹 (Introduction) This is our second article in a series wh…

ubuntu恢復系統_Ubuntu恢復菜單:揭開Linux系統恢復神秘面紗

ubuntu恢復系統Don’t try to convince yourself otherwise: along with all the good stuff, you’re going to have bad days with Linux.否則&#xff0c;請不要試圖說服自己&#xff1a;與所有好的東西一起&#xff0c;您將在Linux上度過糟糕的日子。 You (or the users y…

linux與磁盤相關的內容

本節所講內容1.認識SAS-SATA-SSD-SCSI-IDE硬盤2.使用fdisk對磁盤進行操作&#xff0c;分區&#xff0c;格式化3.開機自動掛載分區4.使用parted操作大于等于4T硬盤5.擴展服務器swap內存空間 MBR(Master Boot Record)主引導記錄&#xff0c;也就是現有的硬盤分區模式。MBR分區的標…

leetcode 87. 擾亂字符串(dp)

使用下面描述的算法可以擾亂字符串 s 得到字符串 t &#xff1a; 如果字符串的長度為 1 &#xff0c;算法停止 如果字符串的長度 > 1 &#xff0c;執行下述步驟&#xff1a; 在一個隨機下標處將字符串分割成兩個非空的子字符串。即&#xff0c;如果已知字符串 s &#xff0c…

頁面布局

頁面布局兩大類&#xff1a;   主站&#xff1a; 1 <div classpg-header> 2 <div stylewidth:980px;margin:0 auto;> 3 內容自動居中 4 </div> 5 <div classpg-content></div> 6 <div classpg-footer></div&…

sonar:默認的掃描規則

https://blog.csdn.net/liumiaocn/article/details/83550309 https://note.youdao.com/ynoteshare1/index.html?id3c1e6a08a21ada4dfe0123281637e299&typenote https://blog.csdn.net/liumiaocn/article/details/83550309 文本版&#xff1a; soanr規則java版 …

多變量線性相關分析_如何測量多個變量之間的“非線性相關性”?

多變量線性相關分析現實世界中的數據科學 (Data Science in the Real World) This article aims to present two ways of calculating non linear correlation between any number of discrete variables. The objective for a data analysis project is twofold : on the one …

wp博客寫文章500錯誤_500多個博客文章教我如何撰寫出色的文章

wp博客寫文章500錯誤Ive written a lot of blog posts. Somewhere north of 500 to be exact. All of them are technical. 我寫了很多博客文章。 確切地說是在500以北的某個地方。 所有這些都是技術性的。 About two dozen of them are actually good. 實際上大約有兩打是不錯…