Selenium (Python 인터페이스 사용 및 여러 브라우저에서)으로 복잡한 Javascript 인터페이스를 테스트하려고합니다. 양식의 여러 버튼이 있습니다.
<div>My Button</div>
“My Button”(또는 “my button”또는 “button”과 같이 대소 문자를 구분하지 않는 부분 일치)을 기반으로 버튼을 검색하고 싶습니다.
나는 명백한 것을 놓치고 있다고 느끼는 정도로 놀랍도록 어려운 것을 발견하고 있습니다. 내가 지금까지 가장 좋은 것은 :
driver.find_elements_by_xpath('//div[contains(text(), "' + text + '")]')
그러나 이것은 대소 문자를 구분합니다. 내가 시도한 또 다른 것은 페이지의 모든 div를 반복하고 element.text 속성을 확인하는 것입니다. 그러나 다음과 같은 상황이 발생할 때마다 :
<div class="outer"><div class="inner">My Button</div></div>
div.outer에는 “My Button”도 텍스트로 사용됩니다. 그 문제를 해결하기 위해 div.outer가 div.inner의 부모인지 확인하려고했지만 그 방법을 알 수 없었습니다 (element.get_element_by_xpath ( ‘..’)는 요소의 부모를 반환하지만 div.outer와 같지 않은 테스트). 또한 적어도 Chrome 웹 드라이버를 사용하면 페이지의 모든 요소를 반복하는 것이 실제로 느린 것 같습니다.
아이디어?
편집 :이 질문은 약간 모호하게 나왔습니다. 더 구체적인 버전을 여기 에서 묻고 대답했습니다 : 자식 요소 텍스트를 포함하지 않고 Selenium WebDriver에서 요소를 텍스트로 얻는 방법 (파이썬 API를 통해)?
답변
다음을 시도하십시오 :
driver.find_elements_by_xpath("//*[contains(text(), 'My Button')]")
답변
다음과 같은 xpath를 시도 할 수 있습니다.
'//div[contains(text(), "{0}") and @class="inner"]'.format(text)
답변
페이지 객체 패턴과 함께 사용할 수도 있습니다. 예 :
이 코드를 사용해보십시오 :
@FindBy(xpath = "//*[contains(text(), 'Best Choice')]")
WebElement buttonBestChoice;
답변
// *는 HTML 태그를 찾습니다. Button 및 div 태그에 공통적 인 텍스트가 있고 // *가 범주 인 경우 예상대로 작동하지 않습니다. 특정을 선택해야하는 경우 HTML 요소 태그를 선언하여 가져올 수 있습니다. 처럼:
driver.find_element_by_xpath("//div[contains(text(),'Add User')]")
driver.find_element_by_xpath("//button[contains(text(),'Add User')]")
답변
흥미롭게도 거의 모든 답변은 xpath의 기능 과 관련이 있으며 OP의 요청과 달리 contains()
대소 문자를 구분 한다는 사실을 무시합니다 .
대소 문자를 구분하지 않으면 xpath 1.0 (현대 브라우저가 지원하는 버전) 에서 달성 할 수 있지만 translate()
기능 을 사용하는 것은 좋지 않습니다 . 변환 표를 사용하여 소스 문자를 원하는 형식으로 대체합니다.
모든 대문자 문자의 테이블을 구성하면 노드의 텍스트를 효과적으로 더 낮은 () 형식으로 변환하여 대소 문자를 구분하지 않는 일치를 허용합니다 (여기서는 특권이 있습니다) .
[
contains(
translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
'my button'
)
]
# will match a source text like "mY bUTTon"
전체 파이썬 호출 :
driver.find_elements_by_xpath("//*[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZЙ', 'abcdefghijklmnopqrstuvwxyzй'), 'my button')]")
당연히이 방법에는 단점이 있습니다. 주어진 바와 같이 라틴어 텍스트에 대해서만 작동합니다. 유니 코드 문자를 다루려면 번역 테이블에 해당 문자를 추가해야합니다. 위 샘플에서 마지막 문자는 키릴 문자입니다 "Й"
.
그리고 브라우저가 xpath 2.0 이상을 지원하는 세계에 살았다면 (곧 올 수는 없지만) , lower-case()
(로케일을 완전히 인식하지는 못함) 기능을 사용할 수 있었으며 matches
(정규 검색을 위해 경우에 따라) -둔감 한 ( 'i'
) 플래그).
답변
제공 한 HTML에서 :
<div>My Button</div>
텍스트 My Button
는 innerHTML
주위에 공백이 없으므로 text()
다음과 같이 쉽게 사용할 수 있습니다 .
my_element = driver.find_element_by_xpath("//div[text()='My Button']")
참고 :
text()
컨텍스트 노드의 모든 텍스트 노드 자식을 선택합니다
선행 / 후행 공백이있는 텍스트
시작 부분에 공백이 포함 된 관련 텍스트를 넣으십시오 .
<div> My Button</div>
또는 끝에 :
<div>My Button </div>
또는 양쪽 끝에서 :
<div> My Button </div>
이 경우 두 가지 옵션이 있습니다.
-
contains()
첫 번째 인수 문자열에 두 번째 인수 문자열이 포함되어 있는지 여부를 판별하고 다음과 같이 부울 true 또는 false를 리턴 하는 함수를 사용할 수 있습니다 .my_element = driver.find_element_by_xpath("//div[contains(., 'My Button')]")
-
normalize-space()
문자열에서 선행 및 후행 공백을 제거하고 공백 문자 시퀀스를 단일 공백으로 바꾸고 결과 문자열을 다음과 같이 반환하는 함수를 사용할 수 있습니다 .driver.find_element_by_xpath("//div[normalize-space()='My Button']]")
변수 텍스트에 대한 xpath
텍스트가 변수 인 경우 다음을 사용할 수 있습니다.
foo= "foo_bar"
my_element = driver.find_element_by_xpath("//div[.='" + foo + "']")
답변
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(), 'YourTextHere')]")));
assertNotNull(driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")));
String yourButtonName=driver.findElement(By.xpath("//*[contains(text(), 'YourTextHere')]")).getAttribute("innerText");
assertTrue(yourButtonName.equalsIgnoreCase("YourTextHere"));