I tried to save screenshot of failure testcase in selenium python project by using driver.save_screenshot() method. I specified my folder as parameter. But can't see failed screenshot in my project. Here is the code.
self.driver.save_screenshot(".//Screenshots//"+"test_homePageTitle.png")
Here is the absolute path - /Users/cherry/Documents/Selenium pj/nopcommerceApp2/Screenshots
I want to save failed testcase as screenshot in my specific folder
Here is the full code:
import time
from pageObjects.loginPage import LoginPage
from utilities.readProperties import ReadConfig
class Test_001_Login:
baseURL = ReadConfig.getApplicationURL()
username = ReadConfig.getUseremail()
password = ReadConfig.getPassword()
def test_homePageTitle(self, setup):
self.driver = setup
self.driver.get(self.baseURL)
act_title = self.driver.title
self.driver.close()
if act_title == "Your store. Login":
assert True
else:
time.sleep(5)
# self.driver.save_screenshot("./nopcommerceApp2/Screenshots" + "test_homePageTitle.png")
self.driver.save_screenshots('.//Screenshots//"+"test_homePageTitle.png')
self.driver.close()
assert False
def test_login(self, setup):
self.driver = setup
self.driver.get(self.baseURL)
time.sleep(10)
self.lp = LoginPage(self.driver)
self.lp.setUserName(self.username)
self.lp.setPassword(self.password)
self.lp.clickLogin()
act_title = self.driver.title
self.driver.close()
if act_title == "Dashboard / nopCommerce administration":
assert True
else:
time.sleep(5)
self.driver.save_screenshot(".\\Screenshots\\" + "test_login.png")
self.driver.close()
assert False
it is not a sustainable way. Instead of it, you can use such reporting plugin.
I may sugges you pytest-html
pip install pytest-html
Then add foolowing code into your conftest.py
# to add screenshot for failed steps
#mark.hookwrapper
def pytest_runtest_makereport(item, call):
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call':
xfail_state = hasattr(report, 'wasxfail')
if (report.skipped and xfail_state) or (report.failed and not xfail_state):
mydriver = item.funcargs['driver']
screenshot = mydriver.get_screenshot_as_base64()
extra.append(pytest_html.extras.image(screenshot, ''))
report.extra = extra
Related
I am using pytest.mark.parametrize for data driven testing. Now when I am generating the html report, the test case name is coming like below which includes all the parameters(data). My goal is to capture only the test case name like "test_RSA_Health" and remove all additional details from the "Test" column of the report. Is it possible?
My Code:
conftest
import time
import allure
import pytest
from allure_commons.types import AttachmentType
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from Utilities.filepath import *
#pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
setattr(item, "rep_" + rep.when, rep)
test_fn = item.obj
docstring = getattr(test_fn, '__doc__')
if docstring:
rep.nodeid = docstring
return rep
#pytest.fixture(scope="function")
def selenium_driver(request):
chrome_options = Options()
chrome_options.add_argument("--headless")
# chrome_options.add_argument("--window-size=1920,1080")
# chrome_options.add_argument('--start-maximized')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
# chrome_options.add_argument("--disable-extensions")
# chrome_options.add_argument('disable-infobars')
s = Service("C:\\Users\\aprat\\OneDrive\\Desktop\\selenium\\chromedriver98\\chromedriver.exe")
url = "https:test.com"
driver = webdriver.Chrome(service=s, options=chrome_options)
driver.maximize_window()
driver.set_window_size(1200, 600)
driver.get(url)
driver.find_element(By.NAME, "user_name").send_keys("9998887776")
driver.find_element(By.NAME, "password_name").send_keys("qwerty123")
driver.find_element(By.XPATH, "//button[#type= 'submit']").click()
time.sleep(3)
request.cls.driver = driver
yield driver
driver.close()
#pytest.fixture()
def log_on_failure(request, selenium_driver):
yield
item = request.node
driver = selenium_driver
if item.rep_call.failed:
allure.attach(driver.get_screenshot_as_png(), name="screenshot", attachment_type=AttachmentType.PNG)
test script:
import time
import pytest
from Pages.HomePage import HomePage
from TestCases.BaseTest import BaseTest
from Utilities import dataProvider
class Test_RSA_Health(BaseTest):
#pytest.mark.parametrize("pin,sumvalue,mobileno,selfage,fullname,email,firstname,lastname,dob,income,pan,designation,add1,add2,height,weight,nomfirstname,nomlastname,nomdob", dataProvider.get_data("rsa_health"))
def test_RSA_Health(self,pin,sumvalue,mobileno,selfage,fullname,email,firstname,lastname,dob,income,pan,designation,add1,add2,height,weight,nomfirstname,nomlastname,nomdob):
home = HomePage(self.driver)
healthinsuranepage = home.SelectHealth()
self.VerifyPresence_PinCodeTextBox()
healthinsuranepage.landing_page()
healthinsuranepage.InputPin(pin)
healthinsuranepage.SelectSum(str(sumvalue))
healthinsuranepage.InputMobileNo(mobileno)
insureddetailspage = healthinsuranepage.ClickNext()
self.VerifyPresence_SelfCheckBox()
insureddetailspage.landing_page()
insureddetailspage.SelectMemberSelf()
self.VerifyPresence_SelfAgeTextBox()
insureddetailspage.InputAge(selfage)
time.sleep(2)
quotespage = insureddetailspage.ClickNext()
time.sleep(5)
quotespage.landing_page()
quotespage.ShareQuotes()
time.sleep(3)
quotespage.SelectAllQuotes()
time.sleep(2)
quotespage.ClickNext1()
self.VerifyPresence_NameTextBox()
quotespage.InputName(fullname)
quotespage.InputEmail(email)
quotespage.InputMobileNo(mobileno)
time.sleep(2)
quotespage.ClickSubmit()
time.sleep(2)
self.VerifyPresence_CloseButton()
time.sleep(2)
quotespage.ClickCloseButton()
time.sleep(2)
policydetailspage = quotespage.RSAPlanSelect()
time.sleep(3)
propdetailspage = policydetailspage.ConfirmTenure()
policydetailspage.landing_page()
self.VerifyPresence_FirstNameTextBox()
propdetailspage.landing_page()
propdetailspage.InputFirstName(firstname)
propdetailspage.InputLastName(lastname)
propdetailspage.InputDOB(dob)
propdetailspage.SelectPropGender()
propdetailspage.InputEmailId(email)
propdetailspage.InputContactNo(mobileno)
propdetailspage.InputIncome(income)
propdetailspage.InputPANCard(pan)
propdetailspage.SelectOccupationDropdown()
self.VerifyPresence_SelectOccupationOption()
propdetailspage.SelectOccupation()
propdetailspage.InputDesignation(designation)
propdetailspage.SelectMaritalStatusDropdown()
self.VerifyPresence_MaritalStatusOption()
propdetailspage.SelectMaritalStatus()
propdetailspage.SelectEducationDropdown()
self.VerifyPresence_QualificationOption()
propdetailspage.SelectQualification()
propdetailspage.SelectTPANameDropdown()
self.VerifyPresence_TPANameOption()
propdetailspage.SelectTPA()
propdetailspage.InputAdd1(add1)
propdetailspage.InputAdd2(add2)
selfdetailspage = propdetailspage.ClickNext()
self.VerifyPresence_SelfFirstNameTextBox()
selfdetailspage.landing_page()
selfdetailspage.InputSelfFirstName(firstname)
selfdetailspage.InputSelfLastName(lastname)
selfdetailspage.InputSelfDOB(dob)
selfdetailspage.SelectSelfGender()
selfdetailspage.InputSelfHeight(height)
selfdetailspage.InputSelfWeight(weight)
selfdetailspage.InputSelfDesignation(designation)
selfdetailspage.InputNomineeFName(nomfirstname)
selfdetailspage.InputNomineeLName(nomlastname)
selfdetailspage.InputNomineeDOB(nomdob)
selfdetailspage.SelectNomineeGender()
selfdetailspage.SelectNomineeRltnDropdown()
self.VerifyPresence_NomRelationOption()
selfdetailspage.SelectNomineeRelation()
questionariespage = selfdetailspage.ClickNext()
time.sleep(4)
questionariespage.landing_page()
policyreviewpage = questionariespage.ClickNext()
self.VerifyPresence_NameValidationText()
policyreviewpage.landing_page()
proposer_name = policyreviewpage.GetName()
proposer_email = policyreviewpage.GetEmail()
proposer_mobno = policyreviewpage.GetPhoneNo()
try:
assert proposer_name == fullname
assert proposer_email == email
assert int(proposer_mobno) == mobileno
except Exception as e:
raise e
policyreviewpage.FinalSubmit()
self.VerifyPresence_ShareButton()
policyreviewpage.SharePolicy()
Like this:
test_details = [{'pin': 444, 'sumvalue': 444,.....}]
def pytest_generate_tests(metafunc):
if 'test_data' in metafunc.fixturenames:
metafunc.parametrize("test_data", test_details)
def test_RSA_Health(self,test_data)
pin = test_data['pin']
Or like this:
test_details = [{'pin': 444, 'sumvalue': 444,.....}]
#pytest.mark.parametrize("test_data", [(test_details)]
def test_RSA_Health(self,test_data)
pin = test_data['pin']
I have used following code to add screenshots in pytest-html report, it's not giving any error but .png file is blank after running the code.
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
Extends the PyTest Plugin to take and embed screenshot in html report, whenever test fails.
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call' or report.when == "setup":
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):
file_name = report.nodeid.replace("::", "_") + ".png"
_capture_screenshot(file_name)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:304px;height:228px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot(name):
driver.get_screenshot_as_file(name)
#pytest.fixture(scope='session', autouse=True)
def browser():
global driver
if driver is None:
driver = webdriver.Chrome()
return driver
I am trying to modify my existing Selenium Pytest Page Object Model setup method to make a call to Selenium Grid on Ip "http://localhost:4444/wd/hub".
However when I try to run my test class I am getting a Error forwarding the new session cannot find : Capabilities exception. Please find below the code:
conftest.py
import options as options
import pytest
from selenium import webdriver
from selenium.webdriver import DesiredCapabilities
from webdriver_manager.chrome import ChromeDriverManager
selenium_grid_url = "http://192.168.1.8:4444/wd/hub"
#pytest.fixture()
def setup():
# if browser=='chrome':
# driver=webdriver.Chrome(ChromeDriverManager().install())
# else:
# driver=webdriver.Ie()
dc = DesiredCapabilities.CHROME
dc['platform'] = "WIN10"
dc['version'] = '89'
options = webdriver.ChromeOptions()
driver = webdriver.Remote(desired_capabilities=dc,
command_executor=selenium_grid_url, options=options)
return driver
#
# def pytest_addoption(parser): # This will get browser value from Command Line
# parser.addoption("--browser")
#
# #pytest.fixture()
# def browser(request): # This will return the Browser value to setup method
# return request.config.getoption("--browser")
##############----------------PyTest HTML Report--------------###########################
# It is hook for Adding Environment info to HTML Report
def pytest_configure(config):
config._metadata['Project Name'] = 'nop Commerce'
config._metadata['Module Name'] = 'Customers'
config._metadata['Tester'] = 'Ishan'
# It is hook for delete/Modify Environment info to HTML Report
#pytest.mark.optionalhook
def pytest_metadata(metadata):
metadata.pop("JAVA_HOME", None)
metadata.pop("Plugins", None)
Page Class : LoginPage.py
import time
from selenium import webdriver
class LoginPage:
textbox_username_id="Email"
textbox_password_id="Password"
button_login_xpath="//input[#class='button-1 login-button']"
link_logout_linktext="Logout"
def __init__(self,driver):
self.driver=driver
def setUserName(self,username):
self.driver.find_element_by_id(self.textbox_username_id).clear()
self.driver.find_element_by_id(self.textbox_username_id).send_keys(username)
def setPassword(self,password):
self.driver.find_element_by_id(self.textbox_password_id).clear()
self.driver.find_element_by_id(self.textbox_password_id).send_keys(password)
time.sleep(10)
def clickLogin(self):
self.driver.find_element_by_xpath(self.button_login_xpath).click()
def clickLogout(self):
self.driver.find_element_by_link_text(self.link_logout_linktext).click()
My pytest test file:- test_login.py
import pytest
from selenium import webdriver
from pageObjects.LoginPage import LoginPage
from utilities.readProperties import ReadConfig
from utilities.customLogger import LogGen
class Test_001_Login:
baseURL = ReadConfig.getApplicationURL()
username = ReadConfig.getUsername()
password = ReadConfig.getPassword()
logger= LogGen.loggen()
#pytest.mark.sanity
#pytest.mark.regression
def test_homePageTitle(self, setup):
self.logger.info("*******************Test_001_Login***********************")
self.logger.info("*******************Verifying Home Page Title***********************")
self.driver = setup
self.driver.maximize_window()
self.driver.get(self.baseURL)
act_title = self.driver.title
if act_title == "Your store. Login":
assert True
self.logger.info('*******************Test Passed - HomePageTitle***********************')
self.driver.close()
else:
self.driver.save_screenshot("D:\\Python Programs\\SeleniumPavanSDET\\NopCommerce\Screenshots\\" + "test_homePageTitle.png")
self.driver.close()
self.logger.error('*******************Test Failed - HomePageTitle***********************')
assert False
#pytest.mark.sanity
#pytest.mark.regression
def test_login(self,setup):
self.logger.info('*******************Test_001_Login***********************')
self.logger.info('*******************Verifying Login Test**********************')
self.driver = setup
self.driver.maximize_window()
self.driver.get(self.baseURL)
self.lp = LoginPage(self.driver)
self.lp.setUserName(self.username)
self.lp.setPassword(self.password)
self.lp.clickLogin()
act_title = self.driver.title
if act_title == "Dashboard / nopCommerce administration":
assert True
self.logger.info('*******************Test Passed - TestLogin***********************')
self.driver.close()
else:
self.driver.save_screenshot("D:\\Python Programs\\Selenium\\NopCommerce\Screenshots\\"+"test_login.png")
self.driver.close()
self.logger.error('*******************Test Failed - TestLogin***********************')
assert False
Exception:-
> driver = webdriver.Remote(desired_capabilities=dc,
command_executor=selenium_grid_url, options=options)
E selenium.common.exceptions.WebDriverException: Message: Error forwarding the new session cannot find : Capabilities {browserName: chrome, goog:chromeOptions: {args: [], extensions: []}, platform: WIN10, version: 89}
E Stacktrace:
E at org.openqa.grid.web.servlet.handler.RequestHandler.process (RequestHandler.java:118)
E at org.openqa.grid.web.servlet.DriverServlet.process (DriverServlet.java:85)
E at org.openqa.grid.web.servlet.DriverServlet.doPost (DriverServlet.java:69)
E at javax.servlet.http.HttpServlet.service (HttpServlet.java:707)
E at javax.servlet.http.HttpServlet.service (HttpServlet.java:790)
E at org.seleniumhq.jetty9.servlet.ServletHolder.handle (ServletHolder.java:865)
E at org.seleniumhq.jetty9.servlet.ServletHandler.doHandle (ServletHandler.java:535)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.handle (ScopedHandler.java:146)
E at org.seleniumhq.jetty9.security.SecurityHandler.handle (SecurityHandler.java:548)
E at org.seleniumhq.jetty9.server.handler.HandlerWrapper.handle (HandlerWrapper.java:132)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextHandle (ScopedHandler.java:257)
E at org.seleniumhq.jetty9.server.session.SessionHandler.doHandle (SessionHandler.java:1595)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextHandle (ScopedHandler.java:255)
E at org.seleniumhq.jetty9.server.handler.ContextHandler.doHandle (ContextHandler.java:1340)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextScope (ScopedHandler.java:203)
E at org.seleniumhq.jetty9.servlet.ServletHandler.doScope (ServletHandler.java:473)
E at org.seleniumhq.jetty9.server.session.SessionHandler.doScope (SessionHandler.java:1564)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.nextScope (ScopedHandler.java:201)
E at org.seleniumhq.jetty9.server.handler.ContextHandler.doScope (ContextHandler.java:1242)
E at org.seleniumhq.jetty9.server.handler.ScopedHandler.handle (ScopedHandler.java:144)
E at org.seleniumhq.jetty9.server.handler.HandlerWrapper.handle (HandlerWrapper.java:132)
E at org.seleniumhq.jetty9.server.Server.handle (Server.java:503)
E at org.seleniumhq.jetty9.server.HttpChannel.handle (HttpChannel.java:364)
E at org.seleniumhq.jetty9.server.HttpConnection.onFillable (HttpConnection.java:260)
E at org.seleniumhq.jetty9.io.AbstractConnection$ReadCallback.succeeded (AbstractConnection.java:305)
E at org.seleniumhq.jetty9.io.FillInterest.fillable (FillInterest.java:103)
E at org.seleniumhq.jetty9.io.ChannelEndPoint$2.run (ChannelEndPoint.java:118)
E at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.runTask (EatWhatYouKill.java:333)
E at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.doProduce (EatWhatYouKill.java:310)
E at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.tryProduce (EatWhatYouKill.java:168)
E at org.seleniumhq.jetty9.util.thread.strategy.EatWhatYouKill.run (EatWhatYouKill.java:126)
E at org.seleniumhq.jetty9.util.thread.ReservedThreadExecutor$ReservedThread.run (ReservedThreadExecutor.java:366)
E at org.seleniumhq.jetty9.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:765)
E at org.seleniumhq.jetty9.util.thread.QueuedThreadPool$2.run (QueuedThreadPool.java:683)
E at java.lang.Thread.run (None:-1)
Not sure why this error is coming. I have registered my selenium server as hub and also registered respective nodes.
If anybody could help let me know as to why this error is occuring it would be great. Thank you.
Just replaced that step on mine, works fine for me:
selenium_grid_url = "http://localhost:4444/wd/hub"
#pytest.fixture()
def setup():
dc = DesiredCapabilities.CHROME
options = webdriver.ChromeOptions()
driver = webdriver.Remote(desired_capabilities=dc,
command_executor=selenium_grid_url, options=options)
return driver
by the way, how do you launch selenium-grid, like standalone server?like:
java -jar selenium-server-standalone-3.141.59.jar
im very new to python, trying to create reusable code. when i try to call the class Login and function login_user in test_main.py by passing all the arguments that were used under Login class, im getting an error as InvalidArgumentException: Message: invalid argument: 'using' must be a string.
test_main.py file which runs on pytest.
Locators_test is the class of test_Locators.py file where i have all my xpaths
test_Locators.py
class Locators_test():
loginlink_xpath = "//a[#id='login-link']"
login_email = "xxxxx"
login_password = "xxxxx"
loginemail_id = "dnn_ctr1179_Login_txtEmail"
loginpassword_id = "dnn_ctr1179_Login_txtPassword"
clicklogin_id = "dnn_ctr1179_Login_btnLogin"
test_login.py
from Smoketest.locatorfile.test_Locators import Locators_test
class Login():
def __init__(self,driver):
self.driver = driver
def login_user(self,driver):
try:
loginButton = self.driver.find_element((By.XPATH, Locators_test.loginlink_xpath))
while loginButton.click() is True:
break
time.sleep(3)
self.driver.execute_script("window.scrollBy(0,300);")
EmailField = self.driver.find_element((By.ID, Locators_test.loginemail_id))
EmailField.send_keys(Locators_test.login_email)
PasswordField = self.driver.find_element((By.ID, Locators_test.loginpassword_id))
PasswordField.send_keys(Locators_test.login_password)
ClickLogin = self.driver.find_element((By.ID, Locators_test.clicklogin_id))
while ClickLogin.click() is True:
break
time.sleep(5)
userName = self.driver.find_element((By.XPATH, Locators_test.username_xpath))
print("Logged in as", userName.text)
except StaleElementReferenceException or ElementClickInterceptedException or TimeoutException as ex:
print(ex.message)
test_main.py
def test_setup():
driver = webdriver.Chrome(executable_path= Locators_test.browser_path)
driver.maximize_window()
driver.delete_all_cookies()
driver.get(homePage)
driver.implicitly_wait(5)
yield
print("test complete")
def test_login(test_setup):
from Smoketest.pages.test_login import Login
lo = Login(driver)
lo.login_user(((Locators_test.loginlink_xpath,Locators_test.loginemail_id,Locators_test.login_email,Locators_test.loginpassword_id,Locators_test.login_password,Locators_test.clicklogin_id,Locators_test.username_xpath)))
indentations are all fine
I fixed it myself by removing the extra pair of parenthesis from the line
loginButton = self.driver.find_element((By.XPATH, Locators_test.loginlink_xpath))
Right way is
loginButton = self.driver.find_element(By.XPATH, Locators_test.loginlink_xpath)
ps: this applies to all the lines.
This worked for me,
locator = (By.XPATH, Locators_test.loginlink_xpath)
self.driver.find_element(*locator).click()
Explanation: In *<arguments>, all positional arguments other than the first one will be packed in a tuple, as they won't get Changed, the exact property will be reflected in the second step.
I'm automating mobile app with Appium and Python. I need to get a HTML report for the test results.
What I need is to save test results in Html files, for human readable presentation of results. I have tried out a few ways, but nothing worked for me.
Anyone knows how to do it? Thanks in advance.
import os, sys
import glob
import unittest
from appium import webdriver
from time import sleep
PLATFORM_VERSION = '5.1.1'
class EntranceTests(unittest.TestCase):
def setUp(self):
print 'commandline args',sys.argv[1]
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1.1'
desired_caps['deviceName'] = 'CooTel S32'
desired_caps['udid'] = sys.argv[1]
desired_caps['appPackage'] = 'com.android.systemui'
desired_caps['appActivity'] = ' '
url = "http://localhost:{}/wd/hub".format(sys.argv[2])
self.driver = webdriver.Remote(url, desired_caps)
def data_connection(self):
self.driver.orientation = "PORTRAIT"
self.driver.swipe(340, 1, 340, 800, 2000)
notification = self.driver.find_element_by_id('com.android.systemui:id/header')
notification.click()
try:
wifi = self.driver.find_element_by_xpath('//*[contains(#class,"android.widget.TextView") and contains(#text, "WLAN")]')
wifi.is_displayed()
print 'Wifi is switched off'
mobiledata = self.driver.find_element_by_xpath('//android.widget.TextView[contains(#text, "Mobile data")]')
mobiledata.click()
print 'SUCCESS! Switch on Mobile data'
sleep(5)
except:
print 'Wifi is switched on'
wifi_off = self.driver.find_element_by_xpath('//*[contains(#class,"android.widget.ImageView") and contains(#index, "0")]')
wifi_off.click()
print 'SUCCESS! Switch off Wifi'
mobiledata = self.driver.find_element_by_xpath('//android.widget.TextView[contains(#text, "Mobile data")]')
mobiledata.click()
print 'SUCCESS! Switch on Mobile data'
sleep(5)
def testcase_dataAndWifi(self):
self.data_connection()
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(EntranceTests)
result = str(unittest.TextTestRunner(verbosity=2).run(suite))
You can use nose-html-reporting module(pip install nose-html-reporting) for generating HTML reports while using python unittest framework.
Please refer below link for more information:
https://pypi.org/project/nose-html-reporting/