diff --git a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.en.md b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.en.md index b8163f0edc05..768f412d7d60 100644 --- a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.en.md +++ b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.en.md @@ -18,7 +18,7 @@ A Page Object only models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix needs only to be applied in one place. -Page Object is a Design Pattern that has become popular in test automation for +Page Object Model is a Design Pattern that has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to @@ -43,6 +43,7 @@ helpful tips beyond the scope of this user guide. To get you started, we’ll illustrate page objects with a simple example. ### Examples + First, consider an example, typical of test automation, that does not use a page object: @@ -74,7 +75,7 @@ must change. * The ID-locators would be spread in multiple tests, in all tests that had to use this login page. -Applying the page object techniques, this example could be rewritten like this +Applying the page object model, this example could be rewritten like this in the following example of a page object for a Sign-in page. ```java @@ -183,6 +184,7 @@ there are a few basic rules for getting the desired maintainability of your test code. ## Assertions in Page Objects + Page objects themselves should never make verifications or assertions. This is part of your test and should always be within the test’s code, never in a page object. The page object will contain the representation of the page, and the @@ -197,6 +199,7 @@ HomePage constructors check that the expected page is available and ready for requests from the test. ## Page Component Objects + A page object does not necessarily need to represent all the parts of a page itself. This was [noted by Martin Fowler](https://martinfowler.com/bliki/PageObject.html#footnote-panel-object) in the early days, while first coining the term "panel objects". @@ -279,7 +282,7 @@ public class ProductsPage extends BasePage { .stream() .filter(condition) // Filter by product name or price .findFirst() - .orElseThrow(); + .orElseThrow(() -> new RuntimeException("Product not found")); // Error thrown during actual test run } } ``` @@ -347,7 +350,7 @@ public class ProductsTest { } ``` -The page and component are represented by their own objects. Both objects only have methods for the **services** they offer, which matches the real-world application in object-oriented programming. +The page and component are represented by their own objects. Both objects only have methods for the **services** they offer, which matches the real-world application as is the core principle of object-oriented programming. When applications are built, they are not made of a massive page entity. They are built with components contained in a page. Page Component Objects implement the same approach. You can even nest component objects inside other component objects for more complex @@ -356,6 +359,7 @@ components used throughout the site (e.g. a navigation bar), then it may improve maintainability and reduce code duplication. ## Other Design Patterns Used in Testing + There are other design patterns that also may be used in testing. Discussing all of these is beyond the scope of this user guide. Here, we merely want to introduce the concepts to make the reader aware of some of the things that can be done. As @@ -364,12 +368,11 @@ reader to search for blogs on these topics. ## Implementation Notes +Page Objects can be thought of as facing in two directions simultaneously. Facing toward the developer of a test, they represent the **services** offered by a particular page. Facing away from the developer, they should be the only thing that has a deep knowledge of the structure of the HTML of a page (or part of a page) It's simplest to think of the methods on a Page Object as offering the "services" that a page offers rather than exposing the details and mechanics of the page. As an example, think of the inbox of any web-based email system. Amongst the services it offers are the ability to compose a new email, choose to read a single email, and list the subject lines of the emails in the inbox. How these are implemented shouldn't matter to the test. -PageObjects can be thought of as facing in two directions simultaneously. Facing toward the developer of a test, they represent the **services** offered by a particular page. Facing away from the developer, they should be the only thing that has a deep knowledge of the structure of the HTML of a page (or part of a page) It's simplest to think of the methods on a Page Object as offering the "services" that a page offers rather than exposing the details and mechanics of the page. As an example, think of the inbox of any web-based email system. Amongst the services it offers are the ability to compose a new email, choose to read a single email, and list the subject lines of the emails in the inbox. How these are implemented shouldn't matter to the test. - -Because we're encouraging the developer of a test to try and think about the services they're interacting with rather than the implementation, PageObjects should seldom expose the underlying WebDriver instance. To facilitate this, **methods on the PageObject should return other PageObjects**. This means we can effectively model the user's journey through our application. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service when it previously didn't do that), simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way; we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the PageObjects. +Because we're encouraging the developer of a test to try and think about the services they're interacting with rather than the implementation, Page Objects should seldom expose the underlying WebDriver instance. To facilitate this, **methods on the Page Object may return another Page Object, another Page Component Object, or even itself (this)**. This means we can effectively model the user's journey through our application. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service when it previously didn't do that), simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way; we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the Page Objects. -One consequence of this approach is that it may be necessary to model (for example) both a successful and unsuccessful login; or a click could have a different result depending on the app's state. When this happens, it is common to have multiple methods on the PageObject: +One consequence of this approach is that it may be necessary to model (for example) both a successful and unsuccessful login; or a click could have a different result depending on the app's state. When this happens, it is common to have multiple methods on the Page Object: ```java public class LoginPage { @@ -387,7 +390,7 @@ public class LoginPage { } ``` -The code presented above shows an important point: the tests, not the PageObjects, should be responsible for making assertions about the state of a page. For example: +The code presented above shows an important point: the tests, not the Page Objects, should be responsible for making assertions about the state of a page. For example: ```java public void testMessagesAreReadOrUnread() { @@ -407,17 +410,17 @@ public void testMessagesAreReadOrUnread() { } ``` -Of course, as with every guideline, there are exceptions, and one that is commonly seen with PageObjects is to check that the WebDriver is on the correct page when we instantiate the PageObject. This is done in the example below. +Of course, as with every guideline, there are exceptions, and one that is commonly seen with Page Objects is to check that the WebDriver is on the correct page when we instantiate the Page Object. This is done in the example below. -Finally, a PageObject need not represent an entire page. It may represent a section that appears frequently within a site or page, such as site navigation. The essential principle is that there is only one place in your test suite with knowledge of the structure of the HTML of a particular (part of a) page. +Finally, a Page Object need not represent an entire page and can be composed of Page Object Components. These components may represent a section that appears frequently within a site or page, such as site navigation. The essential principle is that there is only one place in your test suite with knowledge of the structure of the HTML of a particular (part of a) page. ## Summary -* The public methods represent the services that the page offers -* Try not to expose the internals of the page +* The public methods represent the services that the page or component offers +* Try not to expose the internals of the page or component * Generally don't make assertions -* Methods return other PageObjects -* Need not represent an entire page +* Methods return other Page Objects, Page Component Objects, or optionally themselves (for fluent syntax) +* Need not represent an entire page all the time * Different results for the same action are modelled as different methods ## Example diff --git a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.ja.md b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.ja.md index 0d958324940a..6d05e5054bbb 100644 --- a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.ja.md +++ b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.ja.md @@ -19,7 +19,7 @@ A Page Object only models these as objects within the test code. This reduces the amount of duplicated code and means that if the UI changes, the fix needs only to be applied in one place. -Page Object is a Design Pattern that has become popular in test automation for +Page Object Model is a Design Pattern that has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to @@ -44,6 +44,7 @@ helpful tips beyond the scope of this user guide. To get you started, we’ll illustrate page objects with a simple example. ### Examples + First, consider an example, typical of test automation, that does not use a page object: @@ -75,7 +76,7 @@ must change. * The ID-locators would be spread in multiple tests, in all tests that had to use this login page. -Applying the page object techniques, this example could be rewritten like this +Applying the page object model, this example could be rewritten like this in the following example of a page object for a Sign-in page. ```java @@ -184,6 +185,7 @@ there are a few basic rules for getting the desired maintainability of your test code. ## Assertions in Page Objects + Page objects themselves should never make verifications or assertions. This is part of your test and should always be within the test’s code, never in a page object. The page object will contain the representation of the page, and the @@ -198,6 +200,7 @@ HomePage constructors check that the expected page is available and ready for requests from the test. ## Page Component Objects + A page object does not necessarily need to represent all the parts of a page itself. This was [noted by Martin Fowler](https://martinfowler.com/bliki/PageObject.html#footnote-panel-object) in the early days, while first coining the term "panel objects". @@ -280,7 +283,7 @@ public class ProductsPage extends BasePage { .stream() .filter(condition) // Filter by product name or price .findFirst() - .orElseThrow(); + .orElseThrow(() -> new RuntimeException("Product not found")); // Error thrown during actual test run } } ``` @@ -348,7 +351,7 @@ public class ProductsTest { } ``` -The page and component are represented by their own objects. Both objects only have methods for the **services** they offer, which matches the real-world application in object-oriented programming. +The page and component are represented by their own objects. Both objects only have methods for the **services** they offer, which matches the real-world application as is the core principle of object-oriented programming. When applications are built, they are not made of a massive page entity. They are built with components contained in a page. Page Component Objects implement the same approach. You can even nest component objects inside other component objects for more complex @@ -357,6 +360,7 @@ components used throughout the site (e.g. a navigation bar), then it may improve maintainability and reduce code duplication. ## Other Design Patterns Used in Testing + There are other design patterns that also may be used in testing. Discussing all of these is beyond the scope of this user guide. Here, we merely want to introduce the concepts to make the reader aware of some of the things that can be done. As @@ -365,12 +369,11 @@ reader to search for blogs on these topics. ## Implementation Notes +Page Objects can be thought of as facing in two directions simultaneously. Facing toward the developer of a test, they represent the **services** offered by a particular page. Facing away from the developer, they should be the only thing that has a deep knowledge of the structure of the HTML of a page (or part of a page) It's simplest to think of the methods on a Page Object as offering the "services" that a page offers rather than exposing the details and mechanics of the page. As an example, think of the inbox of any web-based email system. Amongst the services it offers are the ability to compose a new email, choose to read a single email, and list the subject lines of the emails in the inbox. How these are implemented shouldn't matter to the test. -PageObjects can be thought of as facing in two directions simultaneously. Facing toward the developer of a test, they represent the **services** offered by a particular page. Facing away from the developer, they should be the only thing that has a deep knowledge of the structure of the HTML of a page (or part of a page) It's simplest to think of the methods on a Page Object as offering the "services" that a page offers rather than exposing the details and mechanics of the page. As an example, think of the inbox of any web-based email system. Amongst the services it offers are the ability to compose a new email, choose to read a single email, and list the subject lines of the emails in the inbox. How these are implemented shouldn't matter to the test. - -Because we're encouraging the developer of a test to try and think about the services they're interacting with rather than the implementation, PageObjects should seldom expose the underlying WebDriver instance. To facilitate this, **methods on the PageObject should return other PageObjects**. This means we can effectively model the user's journey through our application. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service when it previously didn't do that), simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way; we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the PageObjects. +Because we're encouraging the developer of a test to try and think about the services they're interacting with rather than the implementation, Page Objects should seldom expose the underlying WebDriver instance. To facilitate this, **methods on the Page Object may return another Page Object, another Page Component Object, or even itself (this)**. This means we can effectively model the user's journey through our application. It also means that should the way that pages relate to one another change (like when the login page asks the user to change their password the first time they log into a service when it previously didn't do that), simply changing the appropriate method's signature will cause the tests to fail to compile. Put another way; we can tell which tests would fail without needing to run them when we change the relationship between pages and reflect this in the Page Objects. -One consequence of this approach is that it may be necessary to model (for example) both a successful and unsuccessful login; or a click could have a different result depending on the app's state. When this happens, it is common to have multiple methods on the PageObject: +One consequence of this approach is that it may be necessary to model (for example) both a successful and unsuccessful login; or a click could have a different result depending on the app's state. When this happens, it is common to have multiple methods on the Page Object: ```java public class LoginPage { @@ -388,7 +391,7 @@ public class LoginPage { } ``` -The code presented above shows an important point: the tests, not the PageObjects, should be responsible for making assertions about the state of a page. For example: +The code presented above shows an important point: the tests, not the Page Objects, should be responsible for making assertions about the state of a page. For example: ```java public void testMessagesAreReadOrUnread() { @@ -408,17 +411,17 @@ public void testMessagesAreReadOrUnread() { } ``` -Of course, as with every guideline, there are exceptions, and one that is commonly seen with PageObjects is to check that the WebDriver is on the correct page when we instantiate the PageObject. This is done in the example below. +Of course, as with every guideline, there are exceptions, and one that is commonly seen with Page Objects is to check that the WebDriver is on the correct page when we instantiate the Page Object. This is done in the example below. -Finally, a PageObject need not represent an entire page. It may represent a section that appears frequently within a site or page, such as site navigation. The essential principle is that there is only one place in your test suite with knowledge of the structure of the HTML of a particular (part of a) page. +Finally, a Page Object need not represent an entire page and can be composed of Page Object Components. These components may represent a section that appears frequently within a site or page, such as site navigation. The essential principle is that there is only one place in your test suite with knowledge of the structure of the HTML of a particular (part of a) page. ## Summary -* The public methods represent the services that the page offers -* Try not to expose the internals of the page +* The public methods represent the services that the page or component offers +* Try not to expose the internals of the page or component * Generally don't make assertions -* Methods return other PageObjects -* Need not represent an entire page +* Methods return other Page Objects, Page Component Objects, or optionally themselves (for fluent syntax) +* Need not represent an entire page all the time * Different results for the same action are modelled as different methods ## Example @@ -492,4 +495,4 @@ public class LoginPage { return submitLogin(); } } -``` \ No newline at end of file +``` diff --git a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.pt-br.md b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.pt-br.md index c96f392b42e3..3484a7a36e41 100644 --- a/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.pt-br.md +++ b/website_and_docs/content/documentation/test_practices/encouraged/page_object_models.pt-br.md @@ -9,57 +9,82 @@ aliases: [ ] --- -Nota: esta página reuniu conteúdos de várias fontes, incluindo -o [Selenium wiki](https://github.com/SeleniumHQ/selenium/wiki/PageObjects) +Note: this page has merged contents from multiple sources, including +the [Selenium wiki](https://github.com/SeleniumHQ/selenium/wiki/PageObjects) -## Visão geral +## Overview -Dentro da interface de usuário (UI) do seu aplicativo web, existem áreas com as quais seus testes interagem. O Page Object modela apenas essas áreas como objetos dentro do código de teste. Isso reduz a quantidade de código duplicado e significa que, se a UI mudar, a correção precisará ser aplicada apenas em um lugar. +Within your web app's UI, there are areas where your tests interact with. +A Page Object only models these as objects within the test code. +This reduces the amount of duplicated code and means that if the UI changes, +the fix needs only to be applied in one place. -Page Object é um padrão de design (Design Pattern) que se tornou popular na automação de testes para melhorar a manutenção de testes e reduzir a duplicação de código. Page Object é uma classe orientada a objetos que serve como interface para uma página do seu AUT (Aplicativo Sob Teste). Os testes usam então os métodos desta classe de Page Object sempre que precisam interagir com a UI dessa página. A vantagem é que, se a UI da página mudar, os próprios testes não precisam mudar, apenas o código dentro do Page Object precisa mudar. Subsequentemente, todas as mudanças para suportar essa nova UI estão localizadas em um lugar. +Page Object Model is a Design Pattern that has become popular in test automation for +enhancing test maintenance and reducing code duplication. A page object is an +object-oriented class that serves as an interface to a page of your AUT. The +tests then use the methods of this page object class whenever they need to +interact with the UI of that page. The benefit is that if the UI changes for +the page, the tests themselves don’t need to change, only the code within the +page object needs to change. Subsequently, all changes to support that new UI +are located in one place. -### Vantagens +### Advantages -* Existe uma separação bem definida entre o código do teste e o código da página especifica. -* Existe um repositório único para os serviços ou operações que a página oferece, em vez de ter esses serviços espalhados pelos testes. +* There is a clean separation between the test code and page-specific code, such as + locators (or their use if you’re using a UI Map) and layout. +* There is a single repository for the services or operations the page offers + rather than having these services scattered throughout the tests. -Em ambos os casos, isso permite que quaisquer modificações necessárias devido a mudanças na UI sejam feitas em um lugar somente. Informações úteis sobre esta técnica podem ser encontradas em vários blogs, pois este 'padrão de design de teste (test design pattern)' está se tornando amplamente utilizado. Encorajamos os leitores que desejam saber mais a pesquisar na internet por blogs sobre este assunto. Muitos já escreveram sobre este padrão de design e podem fornecer dicas úteis além do escopo deste guia do usuário. Para começar, vamos ilustrar Page Object com um exemplo simples. +In both cases, this allows any modifications required due to UI changes to all +be made in one place. Helpful information on this technique can be found on +numerous blogs as this ‘test design pattern’ is becoming widely used. We +encourage readers who wish to know more to search the internet for blogs +on this subject. Many have written on this design pattern and can provide +helpful tips beyond the scope of this user guide. To get you started, +we’ll illustrate page objects with a simple example. -### Exemplos -Primeiro, considere um exemplo, típico da automação de testes, que não usa um objeto de página: +### Examples + +First, consider an example, typical of test automation, that does not use a +page object: ```java /*** - * Testes da funcionalidade de login + * Tests login feature */ public class Login { public void testLogin() { - // preencha os dados de login na página de entrada + // fill login data on sign-in page driver.findElement(By.name("user_name")).sendKeys("userName"); driver.findElement(By.name("password")).sendKeys("my supersecret password"); driver.findElement(By.name("sign-in")).click(); - // verifique se a tag h1 é "Hello userName" após o login + // verify h1 tag is "Hello userName" after login driver.findElement(By.tagName("h1")).isDisplayed(); assertThat(driver.findElement(By.tagName("h1")).getText(), is("Hello userName")); } } ``` -Existem dois problemas com essa abordagem. +There are two problems with this approach. -* Não há separação entre o método de teste e os localizadores do aplicativo em teste (IDs neste exemplo); ambos estão entrelaçados em um único método. Se a UI do aplicativo em teste muda seus identificadores, layout ou como um login é inserido e processado, o próprio teste deve mudar. -* Os localizadores ID estariam espalhados em vários testes, em todos os testes que tivessem que usar esta página de login. +* There is no separation between the test method and the AUT’s locators (IDs in +this example); both are intertwined in a single method. If the AUT’s UI changes +its identifiers, layout, or how a login is input and processed, the test itself +must change. +* The ID-locators would be spread in multiple tests, in all tests that had to +use this login page. -Aplicando as técnicas de Page Object, este exemplo poderia ser reescrito da seguinte forma no exemplo para uma página de login. +Applying the page object model, this example could be rewritten like this +in the following example of a page object for a Sign-in page. ```java import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; /** - * Page Object encapsula a página de login. + * Page Object encapsulates the Sign-in page. */ public class SignInPage { protected WebDriver driver; @@ -80,11 +105,11 @@ public class SignInPage { } /** - * Faz login como um usuário válido + * Login as valid user * * @param userName * @param password - * @return pbjeto da Pagina Inicial + * @return HomePage object */ public HomePage loginValidUser(String userName, String password) { driver.findElement(usernameBy).sendKeys(userName); @@ -95,14 +120,14 @@ public class SignInPage { } ``` -E o objeto de página para uma página inicial poderia parecer assim. +and page object for a Home page could look like this. ```java import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; /** - * Page Object encapsula a Página Inicial + * Page Object encapsulates the Home Page */ public class HomePage { protected WebDriver driver; @@ -119,27 +144,29 @@ public class HomePage { } /** - * Obtém a mensagem (tag h1) + * Get message (h1 tag) * - * @return String da mensagem de texto + * @return String message text */ public String getMessageText() { return driver.findElement(messageBy).getText(); } public HomePage manageProfile() { - // Encapsulamento da página para gerenciar a funcionalidade do perfil + // Page encapsulation to manage profile functionality return new HomePage(driver); } - /* Mais métodos que oferecem os serviços representados pela Página inicial do usuário logado. Estes métodos por sua vez podem retornar mais Page Object, por exemplo, clicar no botão "Compor email" pode retornar um objeto da classe ComposeMail */ + /* More methods offering the services represented by Home Page + of Logged User. These methods in turn might return more Page Objects + for example click on Compose mail button could return ComposeMail class object */ } ``` -Então agora, o teste de login usaria esses dois objetos de página da seguinte maneira. +So now, the login test would use these two page objects as follows. ```java /*** - * Testes da funcionalidade de login + * Tests login feature */ public class TestLogin { @@ -153,22 +180,40 @@ public class TestLogin { } ``` -Há muita flexibilidade em como o Page Object pode ser projetado, mas existem algumas regras básicas para obter a manutenibilidade desejada do seu código de teste. +There is a lot of flexibility in how the page objects may be designed, but +there are a few basic rules for getting the desired maintainability of your +test code. + +## Assertions in Page Objects + +Page objects themselves should never make verifications or assertions. This is +part of your test and should always be within the test’s code, never in a page +object. The page object will contain the representation of the page, and the +services the page provides via methods but no code related to what is being +tested should be within the page object. -## Afirmações em Page Objects -Os Page Objects em si nunca devem fazer verificações ou afirmações. Isso faz parte do seu teste e sempre deve estar dentro do código do teste, nunca em um objeto de página. O objeto de página conterá a representação da página e os serviços que a página fornece por meio de métodos, mas nenhum código relacionado ao que está sendo testado deve estar dentro do objeto de página. +There is one, single, verification which can, and should, be within the page +object and that is to verify that the page, and possibly critical elements on +the page, were loaded correctly. This verification should be done while +instantiating the page object. In the examples above, both the SignInPage and +HomePage constructors check that the expected page is available and ready for +requests from the test. -Há uma única verificação que pode e deve estar dentro do objeto de página, e isso é para verificar se a página e possivelmente elementos críticos na página, foram carregados corretamente. Essa verificação deve ser feita ao instanciar o objeto de página. Nos exemplos acima, tanto os construtores SignInPage quanto HomePage verificam se a página esperada está disponível e pronta para solicitações do teste. +## Page Component Objects -## Objetos Componentes de Página (Page Component Object) -Page Object não precisa necessariamente representar todas as partes de uma página. Isso foi [notado por Martin Fowler](https://martinfowler.com/bliki/PageObject.html#footnote-panel-object) nos primeiros dias, enquanto cunhava o termo "objetos de painel (panel objects)". +A page object does not necessarily need to represent all the parts of a +page itself. This was [noted by Martin Fowler](https://martinfowler.com/bliki/PageObject.html#footnote-panel-object) in the early days, while first coining the term "panel objects". -Os mesmos princípios usados para objetos de página podem ser usados para criar "Objetos Componente de Página", como foi chamado mais tarde, que representam partes discretas da página e podem ser incluídos em Page Object. Esses objetos de componente podem fornecer referências aos elementos dentro dessas partes discretas e métodos para aproveitar a funcionalidade ou comportamento fornecidos por eles. +The same principles used for page objects can be used to +create "Page _Component_ Objects", as it was later called, that represent discrete chunks of the +page and **can be included in page objects**. These component objects can +provide references to the elements inside those discrete chunks, and +methods to leverage the functionality or behavior provided by them. -Por exemplo, uma página de Produtos tem vários produtos. +For example, a Products page has multiple products. ```html - +