BeautifulSoup extract data from certain columns from a table I am getting too much data out - python-2.7

I am trying to extract some data out of my Selenium Test Report html file.
I am getting too much data out of the table of rows and columns.
The data I would like to extract is all columns which have the class value "testcase" and there is a column below with a class value "popup_link" and the text value will say Pass or Fail.
E.g.
<td class='none'><div class='testcase'>test_000001_login_valid_user</div></td>
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.1')" >
pass</a>
I would like the text "test_000001_login_valid_user" and the text "pass"
There are lots of test cases in my report so I would like to iterate over the rows and get the test case name out and the pass or fail text.
My HTML snippet is:
<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>Test Group/Test case</td>
<td>Count</td>
<td>Pass</td>
<td>Fail</td>
<td>Error</td>
<td>View</td>
</tr>
<tr class='passClass'>
<td>Regression_TestCase.RegressionProjectEdit_TestCase.RegressionProject_TestCase_Project_Edit</td>
<td>75</td>
<td>75</td>
<td>0</td>
<td>0</td>
<td>Detail</td>
</tr>
<tr id='pt1.1' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000001_login_valid_user</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.1')" >
pass</a>
<div id='div_pt1.1' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.1').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.1: *** test_login_valid_user ***
test login with a valid user - Passed
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.2' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000002_select_a_project</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.2')" >
pass</a>
<div id='div_pt1.2' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.2').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.2: *** test_login_valid_user ***
test login with a valid user - Passed
*** test_select_a_project ***
08_12_1612_08_03
Selenium_Regression_Edit_Project_Test
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.3' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000003_verify_Lademo_CRM_DataPreview_is_present</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.3')" >
pass</a>
<div id='div_pt1.3' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.3').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.3: *** test_login_valid_user ***
test login with a valid user - Passed
*** test_select_a_project ***
08_12_1612_08_03
Selenium_Regression_Edit_Project_Test
*** Test verify_Lademo_CRM_DataPreview_is_present ***
aSelenium_LADEMO_CRM_DONOTCHANGE
File
498
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
My code is:
from bs4 import BeautifulSoup
table = soup.select_one("#result_table")
for row in table.select("tr.hiddenRow"):
print(" ".join([td.text for td in row.find_all("td")]))
How can i achieve this please?
Thanks, Riaz

Check each row for both, if both exist then extract the text:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html)
for row in soup.select("#result_table tr"):
div, a = row.select_one("div.testcase"), row.select_one("a.popup_link")
if div and a:
print(div.text.strip(), a.text.strip())
which gives you:
(u'test_000001_login_valid_user', u'pass')
(u'test_000002_select_a_project', u'pass')
(u'test_000003_verify_Lademo_CRM_DataPreview_is_present', u'pass')
Of course if they always go together we can simplify to:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html)
for div in soup.select("#result_table tr div.testcase"):
print(div.text.strip(), div.find_next("a", class_="popup_link").text.strip())

Related

BeautifulSoup My extracted data from HTML table does not print out in the same table format. Can i keep the table format

I have a HTML Test Report file with a list of test cases. Each test case is in a row in an HTML table.
I have managed to get the test cases out from the table for each row.
When i write this out into my email code it does not write it out as a table format like in the HTML. I would like to keep the grid lines for the rows and columns so it displays nicely as a table.
My method to extract the data is:
def extract_testcases_from_report_htmltestrunner():
filename = (r"E:\test_runners project\selenium_regression_test\TestReport\ClearCore_Automated_GUI_Regression_Project_TestReport.html")
html_report_part = open(filename,'r')
soup = BeautifulSoup(html_report_part, "html.parser")
for div in soup.select("#result_table tr div.testcase"):
yield div.text.strip().encode('utf-8'), div.find_next("a").text.strip().encode('utf-8')
When i write it into my email code out the output I get is:
test_000001_login_valid_user
pass
test_000002_select_a_project
pass
test_000003_verify_Lademo_CRM_DataPreview_is_present
pass
test_000004_view_data_preview_Lademo_CRM_and_test_scrollpage
pass
My desired output would be in the following format with the table lines if possible or in the same table format as it is in the HTML:
test_000001_login_valid_user pass
test_000002_select_a_project pass
test_000003_verify_Lademo_CRM_DataPreview_is_present pass
test_000004_view_data_preview_Lademo_CRM_and_test_scrollpage pass
The HTML snippet is:
<div class='heading'>
<h1>Test Report</h1>
<p class='attribute'><strong>Start Time:</strong> 2016-10-27 10:06:59</p>
<p class='attribute'><strong>Duration:</strong> 0:57:01.842000</p>
<p class='attribute'><strong>Status:</strong> Pass 93</p>
<p class='description'>Selenium - ClearCore Regression Project Automated Test</p>
</div>
<p id='show_detail_line'>Show
<a href='javascript:showCase(0)'>Summary</a>
<a href='javascript:showCase(1)'>Failed</a>
<a href='javascript:showCase(2)'>All</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>Test Group/Test case</td>
<td>Count</td>
<td>Pass</td>
<td>Fail</td>
<td>Error</td>
<td>View</td>
</tr>
<tr class='passClass'>
<td>Regression_TestCase.RegressionProject_TestCase</td>
<td>47</td>
<td>47</td>
<td>0</td>
<td>0</td>
<td>Detail</td>
</tr>
<tr id='pt1.1' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000001_login_valid_user</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.1')" >
pass</a>
<div id='div_pt1.1' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.1').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.1: *** test_login_valid_user ***
test login with a valid user - Passed
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.2' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000002_select_a_project</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.2')" >
pass</a>
<div id='div_pt1.2' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.2').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.2: *** test_login_valid_user ***
test login with a valid user - Passed
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.3' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000057_run_clean_and_match_process</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.3')" >
pass</a>
<div id='div_pt1.3' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.3').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.3: *** test_login_valid_user ***
test login with a valid user - Passed
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.4' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000058_view_all_records_report_CRM_CRM2_ESCR</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.4')" >
pass</a>
<div id='div_pt1.4' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.4').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.4: *** test_login_valid_user ***
test login with a valid user - Passed
*** Test view_all_records_report - CRM, CRM2, ESCR ***
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.5' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000059_view_matches_report_CRM_CRM2_ESCR</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.5')" >
pass</a>
<div id='div_pt1.5' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.5').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.5: *** test_login_valid_user ***
test login with a valid user - Passed
*** Test view_all_records_report - CRM, CRM2, ESCR ***
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
Is it possible?
The words pass is going onto a new line. If i can separate this out into a column or by a few spaces that would be good.
The word pass is in an a tag in the HTML. The following line of code finds this. Could i put a few spaces or in another column when i extract it?:
yield div.text.strip().encode('utf-8'), div.find_next("a").text.strip().encode('utf-8')
My email message code snippet which writes it out is:
msg = MIMEText("\n ClearCore Automated GUI Project Test Report \n " + "\n" +
"".join([' - '.join(seq) for seq in extract_status_from_report_htmltestrunner()]) + "\n\n" +
'\n'.join([elem
for seq in extract_testcases_from_report_htmltestrunner()
for elem in seq]) + "\n" +
"\n Report location = : \\\storage-1\Testing\Selenium_Test_Report_Results\ClearCore\Selenium VM \n" + "\n")
My code to extract the status from the report is:
def extract_status_from_report_htmltestrunner():
filename = (
r"E:\test_runners 2 edit project\selenium_regression_test\TestReport\ClearCore_Automated_GUI_Regression_Project_TestReport.html")
html_report_part = open(filename, 'r')
soup = BeautifulSoup(html_report_part, "html.parser")
div_heading = soup.find('div', {'class': 'heading'})
p_status = div_heading.find('strong', text='Status:').parent
p_status.find(text=True, recursive=False)
print p_status.text
return p_status.text
Thanks, Riaz
from bs4 import BeautifulSoup
soup = BeautifulSoup(text, 'lxml')
trs = soup.find_all(class_='hiddenRow')
for tr in trs:
row1 = tr.find('td').get_text()
row2 = tr.find('a').get_text(strip=True)
print('{:<55}{:>5}'.format(row1, row2))
out:
test_000001_login_valid_user pass
test_000002_select_a_project pass
test_000057_run_clean_and_match_process pass
test_000058_view_all_records_report_CRM_CRM2_ESCR pass
test_000059_view_matches_report_CRM_CRM2_ESCR pass

BeautifulSoup Python printing out the extracted data from a table the 2nd column is dropping onto a new line. How ot keep it on same line

I have extracted the data I require from the HTML using BeautifulSoup. I am printing out the data into an email. The data from the 2nd column where it says "pass" is dropping onto a newline in the email body. I would like to keep the "pass" text onto the same line as the test case name.
The sample email body is:
ClearCore 5_1_1 Automated GUI Test_IE11_Selenium_VM Test Report
Status: Pass 89 Error 1
test_000001_login_valid_user
pass
test_000002_select_a_project
pass
test_000003_verify_Lademo_CRM_DataPreview_is_present
pass
test_000004_view_data_preview_Lademo_CRM_and_test_scrollpage
pass
I would like the output to be (would be nice to have the pass aligned nicely in a column):
ClearCore 5_1_1 Automated GUI Test_IE11_Selenium_VM Test Report
Status: Pass 89 Error 1
test_000001_login_valid_user pass
test_000002_select_a_project pass
test_000003_verify_Lademo_CRM_DataPreview_is_present pass
test_000004_view_data_preview_Lademo_CRM_and_test_scrollpage pass
My code to extract the data is:
def extract_testcases_from_report_htmltestrunner():
filename = (r"E:\test_runners 2 edit project\selenium_regression_test_5_1_1\TestReport\ClearCore501_Automated_GUI_TestReport.html")
html_report_part = open(filename,'r')
soup = BeautifulSoup(html_report_part, "html.parser")
for div in soup.select("#result_table tr div.testcase"):
yield div.text.strip().encode('utf-8'), div.find_next("a").text.strip().encode('utf-8')
My email code:
from email.mime.text import MIMEText
def send_report_summary_from_htmltestrunner_selenium_report():
msg = MIMEText("\n ClearCore 5_1_1 Automated GUI Test_IE11_Selenium_VM Test Report \n " + "\n" +
"".join([' - '.join(seq) for seq in extract_status_from_report_htmltestrunner()]) + "\n\n" +
'\n'.join([elem
for seq in extract_testcases_from_report_htmltestrunner()
for elem in seq]) + "\n" +
"\n Report location = : \\\storage-1\Testing\Selenium_Test_Report_Results\ClearCore_5_1_1\Selenium VM\IE11 \n")
msg['Subject'] = "ClearCore 5_1_1 Automated GUI Test"
msg['to'] = "cc4_server_dev#company.onmicrosoft.com"
msg['From'] = "system#company.com"
s = smtplib.SMTP()
s.connect(host=SMTP_SERVER)
s.sendmail(msg['From'], msg['To'], msg.as_string())
s.close()
How can i format it so pass is nearly aligned on the same line as the test case name? Instead of pass dropping onto a new line every time.
Thanks, Riaz
The HTML snippet is if it helps:
<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>Test Group/Test case</td>
<td>Count</td>
<td>Pass</td>
<td>Fail</td>
<td>Error</td>
<td>View</td>
</tr>
<tr class='passClass'>
<td>Regression_TestCase.RegressionProjectEdit_TestCase.RegressionProject_TestCase_Project_Edit</td>
<td>75</td>
<td>75</td>
<td>0</td>
<td>0</td>
<td>Detail</td>
</tr>
<tr id='pt1.1' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000001_login_valid_user</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.1')" >
pass</a>
<div id='div_pt1.1' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.1').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.1: *** test_login_valid_user ***
test login with a valid user - Passed
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.2' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000002_select_a_project</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.2')" >
pass</a>
<div id='div_pt1.2' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.2').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.2: *** test_login_valid_user ***
test login with a valid user - Passed
*** test_select_a_project ***
08_12_1612_08_03
Selenium_Regression_Edit_Project_Test
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
<tr id='pt1.3' class='hiddenRow'>
<td class='none'><div class='testcase'>test_000003_verify_Lademo_CRM_DataPreview_is_present</div></td>
<td colspan='5' align='center'>
<!--css div popup start-->
<a class="popup_link" onfocus='this.blur();' href="javascript:showTestDetail('div_pt1.3')" >
pass</a>
<div id='div_pt1.3' class="popup_window">
<div style='text-align: right; color:red;cursor:pointer'>
<a onfocus='this.blur();' onclick="document.getElementById('div_pt1.3').style.display = 'none' " >
[x]</a>
</div>
<pre>
pt1.3: *** test_login_valid_user ***
test login with a valid user - Passed
*** test_select_a_project ***
08_12_1612_08_03
Selenium_Regression_Edit_Project_Test
*** Test verify_Lademo_CRM_DataPreview_is_present ***
aSelenium_LADEMO_CRM_DONOTCHANGE
File
498
</pre>
</div>
<!--css div popup end-->
</td>
</tr>
The issue that you're having is that your code returns the items from extract_testcases_from_report_htmltestrunner() in a singular list that it then joins with the '\n' character. As a simple example, try this test code that replicates your code:
def test_yield(n):
for i in range(n):
yield str(i), str(i+1)
print '\n'.join([elem for seg in test_yield(5) for elem in seg])
That code should return the string: '0\n1\n1\n2\n2\n3\n3\n4\n4\n5'
You need to loop over the elements that come back from your function above and first join those with either a TAB (\t) character, or, better yet, feed those data elements into the framework of an HTML table array if your email message is HTML enabled. Here's a demo of the \t then \n approach, but you can add strings and formatting to make the HTML Table method work:
'\n'.join(elem for elem in ['\t'.join(e) for e in test_yield(5)])
This will first create a list of the elements of test_yield(), then separate those elements with a '\t', then separate those strings with a '\n'
Hope this helps.
(EDIT: Adding Commentary on Creating a 2-Column Effect)
Following comments asking about creating the effect of 2-columns w/o the ability to use HTML tables, you can do something like the following, which uses spacing instead of TABs for consistency and easier coding in your overall package:
from random import randint
def test_yield(n):
for i in range(n):
yield 'A'*(randint(1,10)), 'PASS'
test_lbls = [y for y in test_yield(10)]
max_len = max(len(i[0]) for i in test_lbls)
test_lbls = [(i[0]+' '*((max_len-len(i[0]))+1),i[1]) for i in test_lbls]
for l in test_lbls:
print l[0]
For my test case, it generated output like this:
AAAAAA PASS
AAAA PASS
AAAAA PASS
AAA PASS
A PASS
AAAAA PASS
AAAAAAAA PASS
AAA PASS
AAAAAAAAA PASS
AAAAAAA PASS
You'll have to modify this to work with your function, but the algorithm for space padding should work all the same! GL

Selenium Webdriver Python clicking radio button is showing WebElement object is not callable

I am trying to click on a radio button on a webpage which I am automating in Selenium Webdriver Python.
When my code tries to click on the radio button it is showing the error:
TypeError: 'WebElement' object is not callable:
The full error is:
Traceback (most recent call last):
File "C:\Webdriver\ClearCore\TestCases\MatchConfigrationPage_TestCase.py", line 85, in test_add_match_configuration_possibles_name
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
File "C:\Webdriver\ClearCore\Pages\match_rules_tab.py", line 82, in click_selected_rule_radio_button
radio_button = self.driver.find_element(By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]')
TypeError: 'WebElement' object is not callable
I can find the button using the following XPATH in Firefox XPATH checker.
//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]
My method to call the button and click is as follows:
from selenium.webdriver.common.by import By
def click_selected_rule_radio_button(self, name):
# params name: The name of the data object to be selected for the match rule, e.g. Name, Address
radio_button = self.driver.find_element(By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="%s" and contains(text(), "%s")]//ancestor::tr[1]//input[#type="radio"]' (name, name))
self.driver.execute_script("arguments[0].click()", radio_button)
return self
the name parameter in the method it's value is "Name", %s in the code has the value "Name"
I have also tried the following:
def click_selected_rule_radio_button2(self, name):
# params name: The name of the data object to be selected for the match rule, e.g. Name, Address
#WebDriverWait(self.driver, 20).until(EC.presence_of_all_elements_located((By.ID, 'match_configuration_add_possible_tab_match_rules_ct_mapping_body')))
radio_button = WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]')))
radio_button.click()
return self
From my TestCase class i call the method as follows:
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
code snippet of test case is as follows:
def test_add_match_configuration_possibles_name(self):
print "*** Test add Match Configuration Possibles - Name ***"
projectNavigator = project_navigator.ProjectNavigatorPage(self.driver)
possiblesPage = projectNavigator.select_projectNavigator_item("Possibles") # click Possibles from project navigator
possiblesPage.click_add_possibles_button()
possiblesPage.enter_possible_matches_name_and_description_from_details_tab("name_dob", "date of birth possible match rule")
possibles_match_rules_tab = possiblesPage.click_match_rules_tab()
possibles_match_rules_tab.click_possibles_match_rules_add_button()
possibles_match_rules_tab.enter_match_rule_name("name_dob")
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
The HTML is:
<table id="match_configuration_add_possible_tab_match_rules_ct_mapping_body" cellspacing="0" style="table-layout: fixed; width: 100%;">
<colgroup>
<tbody>
<tr class="GPI5XK1CFG" __gwt_subrow="0" __gwt_row="0">
<td class="GPI5XK1CEG GPI5XK1CGG GPI5XK1CHG">
<div __gwt_cell="cell-gwt-uid-339" style="outline-style:none;" tabindex="0">
<input type="radio" name="rbCrossRow2" />
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CGG">
<div __gwt_cell="cell-gwt-uid-340" style="outline-style:none;">
<span class="" title="Name" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">Name</span>
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CGG GPI5XK1CBH">
<div __gwt_cell="cell-gwt-uid-341" style="outline-style:none;">
<input id="match_configuration_add_possible_tab_match_rules_cb_name" type="checkbox" />
</div>
</td>
</tr>
<tr class="GPI5XK1CEH" __gwt_subrow="0" __gwt_row="1">
<td class="GPI5XK1CEG GPI5XK1CFH GPI5XK1CHG">
<div __gwt_cell="cell-gwt-uid-339" style="outline-style:none;">
<input type="radio" name="rbCrossRow2" />
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CFH">
<div __gwt_cell="cell-gwt-uid-340" style="outline-style:none;">
<span class="" title="Address" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">Address</span>
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CFH GPI5XK1CBH">
</tr>
<tr class="GPI5XK1CFG" __gwt_subrow="0" __gwt_row="2">
<tr class="GPI5XK1CEH" __gwt_subrow="0" __gwt_row="3">
</tbody>
Can anyone see what is wrong, why the radio button is not callable, it will not click it?
Thanks,
Riaz
You can use JavaScript to click radio button.Code is as follow:
driver=webdriver.Chrome('./chromedriver.exe')
driver.get('your URL')
time.sleep(10)
radioButton = driver.find_element_by_xpath("Radio Button Xpath") #like //input[#id='female']
driver.execute_script("arguments[0].click();", radioButton)
#driver.quit()

I have a table of rows with checkboxes in columns. How do i select a particular checkbox

I have the following HTML structure. A table with rows, the 2nd column has the text displayed e.g. Title (in row 1), FName (in row 2), SNAME (in row3), GENDER etc.
The 3rd column has a checkbox for each row.
I am trying to select a particular checkbox. E.g. my method will accept a parameter (the name of the text value in the row e.g. TITLE).
The method will select the checkbox for TITLE.
When i call the method again with parameter FNAME, the checkbox for FNAME will be clicked.
I am using Selenium Webdriver with Python
I have tried the following XPATH to identify the checkbox:
//span[#title="TITLE" and contains(text(), "TITLE")]/following-sibling::*
//span [text()="TITLE"]/../../preceding-sibling::td/div/input[#type="checkbox"]
These do not find the checkbox for the row called TITLE
I can get to the TITLE with the following XPATH.
//span [text()="TITLE"]
My code snippet is:
def add_mapping2(self, name):
try:
checkbox = self.driver.find_element(By.XPATH, '//span [text()="+name+"]/../../preceding-sibling::td/div/input[#type="checkbox"]')
checkbox.click()
except NoSuchElementException, e:
return False
return True
From my unittest.Testcase class I call the method as follows:
class MappingsPage_TestCase(BaseTestCase):
def test_add_mappings(self):
mappingsPage = projectNavigator.select_projectNavigator_item("Mappings")
mappingsPage.add_mapping2("TITLE")
mappingsPage.add_mapping2("SNAME")
The HTML is:
<table id="data_configuration_edit_mapping_tab_mappings_ct_mapping_body" cellspacing="0" style="table-layout: fixed; width: 100%;">
<colgroup>
<tbody>
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="0">
<tr class="GOFU2OVEH GOFU2OVGH GOFU2OVPG GOFU2OVMG" __gwt_subrow="0" __gwt_row="1">
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHG GOFU2OVHH GOFU2OVAH GOFU2OVNG">
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHH GOFU2OVAH GOFU2OVNG">
<div __gwt_cell="cell-gwt-uid-792" style="outline-style:none;">
<span title="TITLE" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">TITLE</span>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHH GOFU2OVBH GOFU2OVOG GOFU2OVAH GOFU2OVNG">
<div __gwt_cell="cell-gwt-uid-793" style="outline-style:none;" tabindex="0">
<input type="checkbox" checked="" tabindex="-1"/>
</div>
</td>
</tr>
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="2">
<td class="GOFU2OVEG GOFU2OVGG GOFU2OVHG">
<div __gwt_cell="cell-gwt-uid-791" style="outline-style:none;">
<input type="radio" name="rbCrossRow124"/>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVGG">
<div __gwt_cell="cell-gwt-uid-792" style="outline-style:none;">
<span class="" title="FNAME" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">FNAME</span>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVGG GOFU2OVBH">
<div __gwt_cell="cell-gwt-uid-793" style="outline-style:none;">
<input type="checkbox" tabindex="-1"/>
</div>
</td>
</tr>
<tr class="GOFU2OVEH" __gwt_subrow="0" __gwt_row="3">
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="4">
<tr class="GOFU2OVEH" __gwt_subrow="0" __gwt_row="5">
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="6">
more rows with names with checkboxes etc......
</tbody>
</table>
What XPATH could I use to get the checkbox for TITLE, FNAME etc?
I have the table ID "data_configuration_edit_mapping_tab_mappings_ct_mapping_body"
Maybe there is a way to start from the table ID and use a for loop to iterate through the rows and find the particular checkbox?
Thanks.
Riaz
you would use the following xpath expression
String xpath = "//span[#title = 'TITLE']/ancestor::tr[1]//input[#type = 'checkbox']"
What it does:
first search for a span element with your parameter (pls change 'TITLE' to the variable you are using)
then find the first ancestor element that is a tr-element
from there find the input element that is your checkbox within this tr-element
You could then refine to sth like this:
WebElement table = driver.findElement(By.id("data_configuration_edit_mapping_tab_mappings_ct_mapping_body"));
WebElement checkbox = table.findElement(By.xpath(xpath));
For the interest of others whom come across a similar problem. My Python code which I have used for the above answer is:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
def add_mapping(self, name):
wait = WebDriverWait(self.driver, 10)
try:
checkbox = wait.until(EC.element_to_be_clickable((By.XPATH, '//span[#title = "%s"]/ancestor::tr[1]//input[#type = "checkbox"]' % name)))
#table_id = self.driver.find_element(wait.until(EC.element_to_be_clickable(By.ID, 'data_configuration_edit_mapping_tab_mappings_ct_mapping_body')))
#checkbox = table_id.find_element(By.XPATH, '//span[#title = "TITLE"]/ancestor::tr[1]//input[#type = "checkbox"]')
checkbox.click()
except NoSuchElementException, e:
return False
return True
The table id i commented out also works.

Nokogiri parsing with xpath returns empty string

I have the following HTML:
<div>
<table>
<tr>
<td>
<div class="w135">
<div style="float: left; padding-right: 10px;" class="imageThumbnail playerDiv">
<a href="/sport/tennis/2014/10/djokovic-through-wozniacki-out-china-open-2014101114115427766.html" id="ctl00_ctl00_DataList1_ctl00_Thumbnail1_lnkImage10" target="_parent">
<img src="/mritems/imagecache/89/135/mritems/images/2014/10/1/2014101114447491734_20.jpg" id="ctl00_ctl00_DataList1_ctl00_Thumbnail1_imgSmall10" border="0" class="imageThumbnail">
</a>
</div>
</div>
</td>
</tr>
</table>
</div>
When i attempt the rake, i get the error:
NoMethodError: undefined method `at_css' for ["id","ctl00_cphBody_ctl01_DataList1_ctl00_Thumbnail1_Layout17"]:Array
This is the code:
#request = HTTParty.get(url)
#html = Nokogiri::HTML(#request.body)
#html.css(".w135")[0].map do |item|
url = item.at_css("div.playerDiv a")
puts url.inspect
end
I'm really not sure what the issue is and have been trying to fix this for a while. The error occurs on this line url = item.at_css("div.playerDiv a")
Any suggestion is appreciated!
Thanks
I'd do it using something like:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<div>
<table>
<tr>
<td>
<div class="w135">
<div style="float: left; padding-right: 10px;" class="imageThumbnail playerDiv">
<a href="/sport/tennis/2014/10/djokovic-through-wozniacki-out-china-open-2014101114115427766.html" id="ctl00_ctl00_DataList1_ctl00_Thumbnail1_lnkImage10" target="_parent">
<img src="/mritems/imagecache/89/135/mritems/images/2014/10/1/2014101114447491734_20.jpg" id="ctl00_ctl00_DataList1_ctl00_Thumbnail1_imgSmall10" border="0" class="imageThumbnail">
</a>
</div>
</div>
</td>
</tr>
</table>
</div>
EOT
puts doc.search('.w135 div.playerDiv a').map(&:inspect)
Which outputs:
# >> #<Nokogiri::XML::Element:0x3ff0918b132c name="a" attributes=[#<Nokogiri::XML::Attr:0x3ff0918b1250 name="href" value="/sport/tennis/2014/10/djokovic-through-wozniacki-out-china-open-2014101114115427766.html">, #<Nokogiri::XML::Attr:0x3ff0918b123c name="id" value="ctl00_ctl00_DataList1_ctl00_Thumbnail1_lnkImage10">, #<Nokogiri::XML::Attr:0x3ff0918b1228 name="target" value="_parent">] children=[#<Nokogiri::XML::Text:0x3ff0918a5b6c "\n ">, #<Nokogiri::XML::Element:0x3ff0918a5360 name="img" attributes=[#<Nokogiri::XML::Attr:0x3ff0918a4d20 name="src" value="/mritems/imagecache/89/135/mritems/images/2014/10/1/2014101114447491734_20.jpg">, #<Nokogiri::XML::Attr:0x3ff0918a4cbc name="id" value="ctl00_ctl00_DataList1_ctl00_Thumbnail1_imgSmall10">, #<Nokogiri::XML::Attr:0x3ff0918a4b90 name="border" value="0">, #<Nokogiri::XML::Attr:0x3ff0918a4a28 name="class" value="imageThumbnail">]>, #<Nokogiri::XML::Text:0x3ff091871920 "\n ">]>
If you're trying to access the "href" parameter, instead of using inspect, use:
puts doc.search('.w135 div.playerDiv a').map{ |n| n['href'] }
# >> /sport/tennis/2014/10/djokovic-through-wozniacki-out-china-open-2014101114115427766.html