How to combine POMs (Page Object Models) with Playwright Fixtures for better developer experience

Поделиться
HTML-код
  • Опубликовано: 2 фев 2025

Комментарии • 132

  • @3VAudioVideo
    @3VAudioVideo 10 месяцев назад +4

    Coming from QTP and then to Selenium, I too hated having to initialize the same objects over and over again. You do such a great job explaining things in a very clear and concise way. Love your channel!

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад

      Oh thank you! Happy the video's been helpful. 💙

  • @powertester5596
    @powertester5596 10 месяцев назад +1

    Good to see that I am not the only one doing this approach :-)

  • @nikolaljubicic-mijic5193
    @nikolaljubicic-mijic5193 10 месяцев назад

    This is so great. Sometimes I need to initialize more than a few Object Pages. This is a great workaround. 🤗 I will try this for sure. Keep doing great job.

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад

      Nice! Let us know how it goes. ;)

  • @moonpanda1776
    @moonpanda1776 День назад

    Omg, this is a game changer, i moved from selenium to pw, and didn't understand at all how to implement fixtures correctly

    • @ChecklyHQ
      @ChecklyHQ  17 часов назад

      Happy to hear the video's been valuable. 💙

  • @magnus6114
    @magnus6114 7 месяцев назад +1

    Great video!
    For those interested in further examples. I've written a small framework (package) which uses this approach to easily create POMs called POMWright (npm/github).
    Though the main feature is locator management and automatic nesting/chaining of said locators per POM, aswell as handling session storage.

    • @ChecklyHQ
      @ChecklyHQ  7 месяцев назад

      Thanks for sharing!

    • @Al-oh9yr
      @Al-oh9yr 7 месяцев назад

      Hi Brother. Do you have the same sample repo project for PlayWright with BDD frame work java. Do you have a mail id to reach out?

    • @gulnazmusa2113
      @gulnazmusa2113 2 месяца назад

      What is your repo link

  • @wmln2
    @wmln2 10 дней назад +1

    Beautiful mate! What do you think about the approach of using a PO Manager?

    • @ChecklyHQ
      @ChecklyHQ  9 дней назад

      Hmm... I'll have to do some reading about this. What's a PO Manager? 😅

  • @og4789
    @og4789 10 месяцев назад

    Super super nice thanks 🙏
    I am a big pom fan as I like reusing code and to keep the test case itself short and more readable.
    I also don’t like the initializing with new all the time, now your solution appeals a lot. I will give it a try soon. 👍

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад

      Great 👍

    • @og4789
      @og4789 4 месяца назад

      Just implemented, what a nice hack 🙏

  • @kiranbgowda27
    @kiranbgowda27 6 месяцев назад +3

    Hi, i have a doubt what if newPage opens after you did some operation on home page and you need send that instance to next page like cart page. How to send that newPage to another fixture.

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      Yes, you're correct. If your applications opens new pages / windows then this approach can become tricky. You could still import the POM in your code and initialize it manually, though. :)

    • @kiranbgowda27
      @kiranbgowda27 6 месяцев назад

      @@ChecklyHQ Thanks for clarifying

  • @DiRo0566
    @DiRo0566 8 месяцев назад

    A really beautiful solution, nicely supporting the SOC and SRP coding principles!
    Thanks!

  • @schwertz
    @schwertz 3 месяца назад

    Great tip - as so often with your videos. Thank you so much!

  • @TheSgtFoley
    @TheSgtFoley 7 месяцев назад +1

    Hey, @Checkly! Thanks for the video!
    I have a question regarding this approach: let's say I have around 50 POM in my project so should I add them all to my fixture to use across my tests or is there a better approach to do so? For me, it looks like it will be a bit disorderly to store them just like that

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад +1

      This is a great question! 💙 Let me research this topic a bit and put it on the future video list. Watch the space! 📽️

    • @holaktomas
      @holaktomas 3 месяца назад

      Use the fluent interface pattern and init the POMs in the POM layer. Then you would only need to init a few entrypoints (e.g. LoginPage) in the BaseTest class

  • @animeHeadChef
    @animeHeadChef 5 месяцев назад +1

    Hi great video! I am using playwright with Js.
    But i cant directly do ctrl+click on the functions that i am using within my test case while using fixtures
    For example login is a fixture
    Login.enterName(); dosent take me directly to the function defination.
    Would you happen to know or give any inputs of how i can resolve it?
    Just to enhance devleoplement experience and directly going inside the function.

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад

      If your current tests are based on JS, you should be able to rename them to TS and everything should still work. :)
      But if you don't want to switch, most editors have a type check option even for JS files. I'm unsure if this will solve your issue, but in VS Code you can turn on "checkJS" and this should give you some TS functionality even for JS files.

  • @vivekghevariya2536
    @vivekghevariya2536 4 месяца назад +1

    Hi , I have scenario where after clicking on link on homepage it opens another window tab (page= createOrder page)To interact with createOrder page I need to create another page1 ( created by using waitforevent(popup) )and I passed this Page1 in const createOrderpg = new CreateOrder(page1) but in case of using fixture I am creating an object of CreateOrder inside fixture , how can I pass Page1 into fixture to create object of CreateOrder in fixture

    • @ChecklyHQ
      @ChecklyHQ  4 месяца назад +1

      I don't think, if I understand you correctly, `CreateOrder` can be used as fixture then because it's the result of previous interactions. For the case you describe, I don't think it's a big deal to create a new POM, though. 😅
      So, the described approach is more for "base fixtures" that you set up at the beginning of your test.

  • @mohamedahmed-xh5eu
    @mohamedahmed-xh5eu 6 месяцев назад

    Thanks for this video. That's really helpful. How would this work if we have more than 30 fixtures? Should we create multiple files similar to the base file, or is it ok to group all fixtures in one place eg. base.ts?

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад

      As of now I've seen two approaches to this problem.
      1) use `mergeFixtures` -> playwright.dev/docs/release-notes#merge-test-fixtures
      2) start grouping your fixtures in a huge object e.g. `ui.login`, `ui.cart`, `api.featureA`, ...
      I hope this helps and I put this topic onto the list for future videos. :)

  • @feralgoose7157
    @feralgoose7157 7 месяцев назад +1

    Thanks, I have a question if I am using test.step() in my tests to organize my navigation and interaction. So, I would have a step to login and check I am on the dashbaord and another step to navigate from dashboard to page1 and then either a aftereach or another step to logout. Is it recommended to have one fixture that instantiates all pages need in a test, or / can we extend the test.step() for each navigation interactions? Currently, I use functions to hide this functionality but would be interested in fixture replacement.

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      I'm not really sure I understand. But I abstract functionality with fixtures quite often (with and without POMs).

    • @feralgoose7157
      @feralgoose7157 6 месяцев назад

      @@ChecklyHQ Maybe another question... In the POM, if I have a button.click() on one page, but we want to ensure that maybe network traffic completes prior to checking if the next page is ready. So the interaction between the 2 pages are tightly coupled and maybe we want a toPass() to be used. I know this is a huge edge case, but we do have instances that the button.click() can timeout, since the network traffic is not responsive based on cold app pools. I don't like the idea of having one page know about another page. Does it make sense to create a workflow object to combine the logic so that each page is single responsibility? Rather than breaking the logic in the POM.

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      @@feralgoose7157 I'm not sure I understand and YT comments aren't the best medium without seeing code examples. 😅 But your case sounds like you might want to look at your application. If your page looks ready but isn't and Playwright is too fast, then you might want to check the included UX flaws.

  • @prasannamallisetty7208
    @prasannamallisetty7208 10 месяцев назад

    Excellent video. I became a fan of yours. 😊. Thank you

  • @yurademchenko9924
    @yurademchenko9924 25 дней назад

    Like for the video! I'm really wondering people write: "Hey. It's interesting approach. But what if I have 100500 cases with 100500 pages?"
    Guys, the silver bullet for all of you current own projects doesn't exist. Unfortunatly))

    • @ChecklyHQ
      @ChecklyHQ  25 дней назад +1

      Precisely - this is where POMs fall short big time. For any somewhat serious product, the number of different page objects gets out of hand very quickly. :)
      And you're 100% right, there's no silver bullet, and there will never be one. 🦝

  • @Xenguard
    @Xenguard 5 месяцев назад +1

    Would it not tightly couple the Page Objects using Custom Fixtures and create another "thing" to maintain?
    It sounds like instantiating the Page Objects in tests actually reduces maintenance, since a developer would only have to maintain code in two places, i.e. Page Object and Test, rather than three with the inclusion of a Custom Fixtures.

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад +2

      Sure - that's right. :) If you consider files as "places" to maintain: without fixtures, you have your POM file and the test. With fixtures, you have the POM file, your setup, and your test.
      On the other hand, if you consider code to write, you'll quickly discover that using fixtures will lead to less LOC because you don't have to initialize them over and over again.
      As always, it's a matter of tradeoffs and preference. 🤷 :)

    • @VicusBass
      @VicusBass 5 месяцев назад +1

      From all the annoying maintenance needs I guess maintaining the fixtures is the easiest part

  • @rlagoue
    @rlagoue Месяц назад +1

    Why not making the login method, instantiate and return the dashboard page?

    • @ChecklyHQ
      @ChecklyHQ  Месяц назад +1

      That's of course an option, too. I don't hold strong opinions on how to structure POMs and constructors. But I do like to use fixtures and Playwright's native dependency injection. 🦝

  • @dva_kompota
    @dva_kompota 6 месяцев назад +1

    You can go even further: wrap all your page objects into UI fixture and use only it in your `test('test-name', async({ui}) => {}` statement.
    So in your test you'll have statements like `await ui.loginPage.login(EMAIL, PW)` and `await ui.dashboardPage.isReady()`
    And even further - you can do the same thing for APIs, wrapping all you API objects with CRUD and other methods into API fixture to do things like `await api.user.create(EMAIL, PW)`

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад +1

      Yes, that's a great tip!

    • @ninkambli
      @ninkambli 6 месяцев назад +1

      Can you please give github repo of this example?

    • @Xelvise
      @Xelvise 6 месяцев назад +1

      It would be a lot more helpful if you could write all of these in a GitHub gist with clear description.
      Or, better still, put it all in a repo and share with us your Username or Repo URL.
      That way, we'll better understand how to implement your suggested technique.

    • @dva_kompota
      @dva_kompota 6 месяцев назад

      @ninkambli @Xelvise I don't know why, but my comments with links or even GH repo name are deleted instantly here

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      @@dva_kompota hmm... We didn't delete anything. I'll look into it maybe there's a misconfigured setting.

  • @ppp.1334
    @ppp.1334 2 месяца назад +1

    How about usong cucumer and Playwright? Is it good approach?

    • @ChecklyHQ
      @ChecklyHQ  2 месяца назад

      Unfortunately, I haven't used Cucumber with Playwright, so I can't tell if it's a good approach.

    • @ppp.1334
      @ppp.1334 2 месяца назад +1

      @ChecklyHQ i tried but had problem to run it, so abandoned this solution

  • @filipgajic93
    @filipgajic93 8 месяцев назад

    Hi @Checkly, is it possible to use/import fixtures on test.step level ? I know I can pass it as a parameter to the function from test but I'm wondering is there a way to use it the same way you're using it on the test level? Thank you !

    • @ChecklyHQ
      @ChecklyHQ  7 месяцев назад

      I don't think that's possible unfortunately. :/

  • @tomasgomez1480
    @tomasgomez1480 8 месяцев назад

    Nice video! You said that you don't like to use POM, which other design pattern do you prefer?

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      This is a great question and I'll put the answer on the "future video list". Watch the space! 📺

  • @emnznlg
    @emnznlg 10 месяцев назад

    Thank you for the great content! I was wondering why you don't prefer POM and what alternative you use instead. Could you please explain?

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад +1

      My main grudge are the things I mentioned in the video. 1) calling `new` everywhere and initializing all these POMs 2) importing things "outside" the PWT suite.
      Usually I preferred helper functions (helping to avoid `new` but not with the importing). But now with "Fixture POMs" I think I'll go all in and am convinced. :)

  • @Rehank213
    @Rehank213 10 месяцев назад

    Excellent video, which code auto complete plugin you are in Vs Code?

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад +1

      Thanks. It's GitHub Copilot. :)

  • @christiangibbs8534
    @christiangibbs8534 6 месяцев назад

    Nice clean code, but is it possible to preserve state between tests if you are automatically creating a new instance every time you call it?

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад

      Can you explain a bit more. Preserving state between tests doesn't sound right. 😅

    • @056479335
      @056479335 5 месяцев назад

      @@ChecklyHQ I agree, each test should be self contained and not use states created in other test but I see the point of saving a state from other tests. Imagine that you have two tests. One creates an account and the other on for login. Lets say that the create-account-test generates a GUID that the login-test wants to check.

  • @Uradha1
    @Uradha1 8 месяцев назад +1

    Please can you make a video on GItCoPilot on Playwright and how to use it in the test environment?

    • @ChecklyHQ
      @ChecklyHQ  7 месяцев назад

      That's an interesting idea. I'm unsure if we'll do it unfortunately. CoPilot is unfortunately only 50% correct, and I'm on the fence if it's actually useful. 🤷

  • @Runeblade484
    @Runeblade484 Месяц назад +1

    You say you usually don't like page object models. Do you have a video on what you like to use? Or can you at least give me the name so I can look into it?

    • @ChecklyHQ
      @ChecklyHQ  25 дней назад

      Usually I prefer to group functionality based on user actions instead of pages. I also don't like to initialize new page objects all the time. 😅
      As an alternative, I quite often have `user.login`, `user.logout`, ... object methods which I bring in via Playwright fixtures. This objects aren't necessarily bound to specific pages but rather a set of functionality. Of course, this approach is no silver bullet but I like it better than POMs. :)
      I'll put this topic onto the list of ideas for future videos. Thanks!

  • @lukecage9964
    @lukecage9964 6 месяцев назад +1

    Imagine to have a big amount of page-objects, it should be really boring to add all of these in the fixture to be exported..
    in base.ts is it possible to create the MyFixtures and the export const test dynamically? I mean, like reading all the the pages inside /pom and forEach page add it into MyFixtures and into the test const to export

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад +1

      Yeah, reading files should be pretty straightforward, but having the correct types will be tricky if you're writing TS. I'm not sure if one could dynamically create the types without bringing in some "build magic".

  • @iHorus
    @iHorus 5 месяцев назад

    This one's great! And so simple

  • @HelloWorld-xg6nw
    @HelloWorld-xg6nw 10 месяцев назад

    doing exactly the same)
    Just maybe that now I've changed it a bit to have a container with all pages. Like Pages object that stores all pages.
    export class Pages {
    page: Page;
    signInPage: SignInPage;
    dashboardPage: DashboardPage;
    Just because in some complicated e2e tests you interact with too many of them
    And also it helps to create tests which have > 1 user logged in. So my test looks like ({ adminPages, employeePages }). And sign in happens in setup.ts & fixtures. Very flexible. Perhaps a bit not efficient if you have too many pages in your web site, i.e. 50+. But for my case quite good to follow this approach

  • @harshasuraweera
    @harshasuraweera 10 месяцев назад

    I used this way and it is pretty straightforward. But I think there’s a limitation on BeforeAll hooks

    • @ChecklyHQ
      @ChecklyHQ  9 месяцев назад +1

      That's interesting. Thanks! Do you have an example of when this approach hits limits? 🤔

    • @harshasuraweera
      @harshasuraweera 9 месяцев назад

      @@ChecklyHQ I got the issue about 1 year back so not sure whether it’s fixed now, it was about context and page fixtures not supporting inside beforeAll hook. I was trying to take few preconception steps into beforeAll but due to the mentioned issue it didn’t work. So I moved them into the test level. (and yes it worked with beforeEach)

  • @maniladevotee3595
    @maniladevotee3595 10 месяцев назад

    How was the runtime if you initialize objects even if you do not need it on a specific test case?

    • @ChecklyHQ
      @ChecklyHQ  9 месяцев назад

      That's a great question and I just tested it. First, Playwright will run your defined fixture code for each test case separately and no state is shared. Additionally Playwright somehow checks which fixtures you're planning to use and only runs this code. 🎉 If you define a `LoginPage` fixture this code will only run if you're using the `LoginPage`.

    • @maniladevotee3595
      @maniladevotee3595 7 месяцев назад

      ​​@@ChecklyHQhello, I was thinking if you have a drop-down component. How do you make the drop down locator dynamically e.g(drop-down-option1, drop-down-option2, etc...) if it is initialiazed inside the constructor?

  • @vnukoded
    @vnukoded 5 месяцев назад

    Is there a way to not pass it to every test but to pass it to "beforeEach" or "beforeAll"? Otherwise it doesn't really saves time if you have to pass those args to every test in every testsuite.

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад

      I'm not sure I follow. This video wasn't about saving time, or was it? Could you explain a bit further?

    • @vnukoded
      @vnukoded 5 месяцев назад

      @@ChecklyHQ I guess those workflows got to be convinient, and compared to original POM without fixtures - it doesn't rly help much (I explained why in the first comment). I asked a question to understand if there's a way to make workflow in the video more convinient. If there's no way to acomplish what I asked, or you don't know it - so be it. Not sure what confused you in the first place :)

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад

      @@vnukoded Playwright is all about parallelization, and you can't parallelize with beforeEach/afterEach (more context here: github.com/microsoft/playwright/issues/9948#issuecomment-957328762)
      As a result, fixtures can't be used in beforeEach/afterEach.
      My confusion came from "saving time", should this mean execution time or coding? And it sounded like this video talks about saving time, which it is not. :)

    • @vnukoded
      @vnukoded 5 месяцев назад

      @@ChecklyHQ I meant saving time in terms of coding, yes. Thanks for answering :)

    • @vnukoded
      @vnukoded 4 месяца назад +1

      Okay, I actually missjudged this approach. I can now import tabs/pages/components once, and then use them where they are needed without importing them over and over again. It saves me a lot of time (and nerves) and makes code prettier.

  • @rahulgiri9880
    @rahulgiri9880 9 месяцев назад

    Nice explanation 👍. The only con I see is all pages getting initialised in one shot which is not good from memory perspective.

    • @ChecklyHQ
      @ChecklyHQ  9 месяцев назад +1

      Thanks. I understand your concern but this is not how Playwright fixtures work. If your tests don't define that they want to use a fixture, it won't be initialized.
      So it pretty much should be the same memory consumption. Because the same number of fixtures will be initialized, just in different places.

  • @somystic100
    @somystic100 4 месяца назад

    Thank you 😊

  • @rsganesh9443
    @rsganesh9443 8 месяцев назад

    Super Cool Love it

  • @swapnilbodade1336
    @swapnilbodade1336 5 месяцев назад

    This would be useful in playwright cucumber context. right?

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад

      Good question and unfortunately I don't know the answer, bc I haven't used Playwright cucumber yet. 😅

  • @romag5605
    @romag5605 5 месяцев назад

    looks like timeouts (action , test timeout , expect) are not working with fixtures . anyone faced this issue ?

    • @ChecklyHQ
      @ChecklyHQ  5 месяцев назад +1

      Without an example implementation or code examples, it's very hard to help.
      That said, I haven't had any issues with this approach yet. :)

  • @ЕленаКазакова-о1э4и
    @ЕленаКазакова-о1э4и 5 месяцев назад

    Thsnks a lot!

  • @roblesrt
    @roblesrt 10 месяцев назад

    super cool!

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад

      Happy the video's been valuable. :)

  • @eduardmazur
    @eduardmazur 10 месяцев назад

    I use POM a little bit in a different way, but yours one looks good) I think I'll try to combine both to get something brilliant)😃

    • @ezraarjunapandi3736
      @ezraarjunapandi3736 10 месяцев назад

      Can you explain your method?

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад +1

      Yes, please share anything you come up with. :)

    • @eduardmazur
      @eduardmazur 10 месяцев назад

      @@ezraarjunapandi3736 I create folder "support" where create subfolders for every module in app, create 2 classes Methods and Variables for every module. Then i create index file, where crete export variables for every module. And the result of all this I call only 1 import and use only that class variables which is needed in the test file))) i hope I'm clear have explained)😅

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад +1

      So you're describing a "super POM" so to say? :D

    • @eduardmazur
      @eduardmazur 10 месяцев назад

      @@ezraarjunapandi3736 later I'll try to explain and give thr examples) now I'm outdoor )

  • @andreaskarz
    @andreaskarz 10 месяцев назад

    Cool stuff

  • @luckytima2315
    @luckytima2315 10 месяцев назад

    What is name vs code themes?

    • @ChecklyHQ
      @ChecklyHQ  9 месяцев назад +1

      I use the `Yi Dark` theme. :)

  • @_unreal_engineer
    @_unreal_engineer 10 месяцев назад

    you rock!

  • @PDuimelaar
    @PDuimelaar 3 месяца назад

    hey man great video! Hopen you can help me out:
    i have multiple applications. Application A and application B. Both have a loginPage. Whats best way to make a difference between these applications and call the right loginpage without changing the name of loginpage.
    I was thinking to call them like
    A.loginPage
    B.loginPage
    then A.loginPage.fillemail()
    OR call like
    applicationA
    applicationB
    then A.loginPage.fillemail()
    Hope you can give me a nice solution

    • @ChecklyHQ
      @ChecklyHQ  3 месяца назад

      Thank you! I'll put this topic on the list for future videos. In your case, I'd start merging fixtures into "fixture objects". So that you'd have `applicationA.loginPage` and `applicationB.loginPage`. There's also some helper utils from Playwright to do exactly this. playwright.dev/docs/release-notes#merge-test-fixtures

  • @hamzawaykonect2016
    @hamzawaykonect2016 8 месяцев назад

    even better is to have it like this without putting the page instance test(
    `testkey | testdescription`, async () => {
    await test.step('step 1 ', async () => {
    await OnePage.function1();
    });
    await test.step('step 2 , async () => {
    await OnePage.function2();
    });
    await test.step('step3 ', async () => {
    await OnePage.function2();
    });
    },
    );

    • @ChecklyHQ
      @ChecklyHQ  7 месяцев назад +1

      But then you have to pass the `page` object into `function1` and `function2` or? But as always, there many ways to do things. 👍

  • @jjjjjj6322
    @jjjjjj6322 6 месяцев назад

    problematic design

    • @ChecklyHQ
      @ChecklyHQ  6 месяцев назад +1

      @@jjjjjj6322 can you explain?

    • @guillermofrancella08
      @guillermofrancella08 4 месяца назад

      ​@@ChecklyHQHe cannot, because it's not a problematic design. Good job!

  • @Muhammad55597
    @Muhammad55597 10 месяцев назад

    thanks for the greate content

    • @ChecklyHQ
      @ChecklyHQ  10 месяцев назад

      Thank you! Happy it's been valuable.