2014-10-15 10 views
22

우리는 다음과 같이 페이지를 링크 : 그것은 더 이상 loginpage로 연결되도록 개발진이 홈페이지를 변경하지 않는 경우Page Object Model은 Cucumber 's Gherkin과 호환됩니까? 테스트 자동화의 페이지 개체 모델로

WebDriver driver = new WebDriver() 
HomePage homePage = new HomePage(driver); 
LoginPage loginPage = homePage.GoToLoginPage(); 
WelcomePage welcomePage = loginPage.Login(); 
etc 
etc 

이의 가장 큰 장점은, 내 홈페이지에 클래스를 업데이트 할 수있다 테스트를 실행하기 전에 (오류로) 업데이트해야하는 모든 테스트를보십시오.

그러나 Gherkin에서는 위의 각 행이 별도의 '단계'를 형성하므로 별도의 메소드가됩니다. 따라서이 연결을 어떻게 수행 할 수 있습니까?

페이지 객체 클래스 (예 : homePage, loginPage 등)의 인스턴스를 크로스 거시기 문 지속 저장소 (예 : specflow POCO 또는 'World')에 배치하는 유일한 방법은 무엇입니까?

+1

아마도이 좋은 [post] (http://thomassundberg.wordpress.com/2011/10/18/testing-a-web-application-with-selenium-2/)가 도움이 될 수 있습니다. – troig

+0

훌륭한 글입니다. 약간의 관심사 만이 여러 단계 클래스가 사용 된 경우 단계간에 전달 된 페이지 오브젝트의 인스턴스가 남아 있지 않을 것입니다. world/ootb 의존성 주입을 사용하면이 문제를 해결할 수 있지만 코드는 모든 페이지 객체 인스턴스의 infWindow를 매우 어지럽게 만든다. –

답변

4

그래, 수많은 개발자 및 테스트 자동화 전문가에게 묻기 때문에 해결책은 연결을 계속하는 것입니다. [e.g. WelcomePage welcomePage = loginPage.loginWithValidUser(validUser)]은가는 길입니다.

단계 (예 : 위의 예에서 welcomePage)에 걸쳐 페이지 객체의 인스턴스를 유지하려면 루비의 오이 구현에서 World Extension과 유사한 기능을 만드는 종속성 삽입 도구를 사용할 수 있습니다. https://cukes.info/docs/reference/java-di

그러나, 대부분의 프로젝트는 의존성 삽입 모듈 도움이됩니다 귀하의 코드를 잘 정리하고 단계 정의 사이에 상태를 공유 : 여기

는 추가 정보를 원하시면입니다. SpecFlow에서

상세 정보 (NET의 공식 오이 구현) :

http://specflow.org/getting-started/beyond-the-basics/

그리고 마지막으로, 나는 사람들을 도울 수있는이 지역 주위에 전체 블로그를 만들었습니다, 작은 오이/페이지부터 , 동등 플라 우

http://www.seligmanventures.com/dev-blog/test-automation-page-object-model-with-gherkin

+1

나는 당신이 이전에 묘사 한 것을 해왔고 실제로 그것을 추천하지는 않을 것입니다. 탐색을 변경하면 컴파일 오류가 발생하지만 문제는 사용자가 작업 (예 : 로그인)과 일어나는 일에 대한 주장 ('환영 페이지로 끝납니다')이 혼합되어 있다는 것입니다. 이것은 패스워드를 잘못했을 때 일어나는 일을 테스트하는 것은 추악합니다. LoginPage loginPage = loginPage.loginButExpectError()와 같은 일을해야만합니다. IT가 점점 더 지저분 해집니다. –

+1

요즘 나는 대신 무엇을 할 것인가? 나는 그 행동을 분리하고 행동이 끝났을 때 내가 어디에 있어야하는지에 대한 주장이다. loginPage.login()과 같은 것; WelcomePage welcomePage = onPage (WelcomePage.class); –

+0

Perryn 잘못된 로그인에 대해 귀하의 의견을 듣지 만, 이는 추가 메소드 (예 : loginWithValidUser() 및 loginWithInvalidUser())를 추가하면 간단히 해결할 수 있습니다. 전체적으로 체인 연결의 이점은 필요한 추가 방법보다 중요합니다. 두 메소드 모두 뒤에있는 코드는 페이지 객체에서 조용히 앉아있는 개인적인 방법으로 외삽 될 수 있습니다. –

-2

많은 토론 후이 주제에 : 객체의 상호 작용은 나에게 큰 관심의 대상이다 giblekin과 페이지 객체 패턴을 사용하는 경우 새 페이지의 인스턴스를 반환하지 않아도됩니다. 일반적으로 POM과 연결하는 이점을 잃어 버리지 만 코드는 틀림없이 더 잘 읽고 덜 복잡해집니다. 이 대안 답변을 게시하면 테스트 커뮤니티로서 우리는 어떤 방법을 사람들이 선호하는지 투표 할 수 있습니다.

+0

느낌이 -2는이 답변에 약간 가혹합니다. 필자가 선호하는 대답은 아니지만 확실히 실용적인 대안이며 복잡성을 줄여줍니다.'개선 된'대답을내는 데 도움이 될 수있는 마이너스 포인트의 이유에 대해 의견을 말하십시오. –

+0

다음은 페이지를 통한 탐색에서 반환 한 페이지 객체를 저장하지 않는 예입니다. https://www.testautomationtribe.com/specflow-with-page -object –

+0

작은 방법이 독립적 인 엔티티로 코드화되어 있기 때문에 의미있는 단계로 시작하는 단계에서 관련 페이지 객체의 인스턴스를 만드는 것이 나에게 지적되면서 특히이 접근법을 좋아했습니다. 그러나이 방법을 구현하려고 시도한 후에는 드라이버 인스턴스를 단계 수준에서 유지해야 할 필요가 있다고 생각합니다. 페이지 개체 내에 캡슐화 된 상태로 유지하고 그 사이를 탐색 할 때 주위를 지나칠 수 있습니다. 이 사람이 생각할 수있는 방법이 있습니까? –

0

대부분의 웹 사이트 (URL을 사용할 수 있음)와 관련하여 제 생각에는 동일한 URL로 이동하는 대신 단순히 URL 대신 URL을 사용하는 것이 가장 좋습니다. 예를 들어

는 :

# Suggested by OP: 
driver = Selenium::Webdriver.for :chrome, prefs: prefs 
homepage = Homepage.new(driver) 
login = homepage.go_to_login 
welcome = login.log_in_as('dave4429') 

# My Suggestion: 
homepage = Url.new('/') 
login = Url.new('/login') 
welcome = Url.new('/welcome') 

이 대신 모든 테스트에 대한 홈 페이지를 시작해야하는 URL에서 시작하는 것을 의미한다. 당신은 여전히 ​​당신이 제안한 방법을 가지지 만, 사용자가 URL 이외의 수단을 통해 페이지에 액세스 할 수 있도록 다른 영역에서 사용됩니다.

그러나 이것은 원 스톱 샵 솔루션이 아닙니다. 모바일 및 데스크톱 응용 프로그램을 사용하는 경우 유일한 옵션은 홈 화면을 통과하는 것일 수 있습니다.이 경우 제안한 방법이 반드시 필요한 것입니다.

"페이지 개체 자체는 테스트 또는 테스트의 일부이며 항상 페이지 개체가 아닌 테스트 코드 내에 있어야합니다." - Selenium HQ

내가 아주 기본적인 일이고, 내가 가장 가능성이처럼 코딩을 사용하려면, 모듈 및 클래스로이 포장 할 준 예 :

google = Project::Pages::Google.new 

google.search_for('Hello, World!') 
expect(google.found_result?).to_equal(true) 

편집 이 외에도, 당신은 오이 오이와 어떻게 작동하는지에 대한 오해가있는 것 같습니다.

단계 자체는 단계 내의 조치에 대한 설명이므로 단계 당 여러 행의 코드를 가질 수 있습니다. 예를 들어

:

Given I am logged in as "dave4429" 
When I have submitted the "Contact Us" form with the following data: 
    | [email protected] | David McBlaine | I want to find out more about your Data Protection services, can I talk to a staff member or get a PDF? | 
Then an email should be sent to "[email protected]" with the details specified 

은 "때"다음과 같이 보일 수 있습니다에 대한 정의 : 그것은 모든 훨씬 당신이 정의 내에서 단계를 분해하는 방법에 따라 달라

When(/^I have submitted the "Contact Us" form with the following data:$/) do |table| 
    rows = table.raw 
    row = rows[0] 

    contact_us.fill_form({email: row[0], username: row[1], message: row[2]}) 
    contact_us.submit_message 
    expect(browser.title).to_equal("Message Sent!") 
end 

.

그것은 당신이 내가 '기술을 사용하는 동안 방법 체인, 다시 밖으로 질문하지 contact_us.fill_form({email: row[0], username: row[1], message: row[2]}).submit_message의 길에서 뭔가를하고 싶은 나에게도 분명이

편집 # 이 연쇄가 각 페이지마다 있어야하는지 또는 모든 것이 하나의 클래스 나 모듈에 포함되어야하는지 여부에 대한 질문은 사용자의 요구에 의해서만 답변 될 수 있습니다.

이것은 단지 하나의 클래스에 너무 많이 넣을 것이고, 그 클래스를 무너 뜨리면 테스터에게 더 많은 컨트롤을 줄 수 있고, 적은 코드가 쓰여질 것이라고 생각합니다.