Page Object Model: когда паттерн становится антипаттерном POM — хорошая идея, пока ваш LoginPage не вырастает до 300 строк и 40 методов.

Я видел такой код. Я сам его писал. Давайте разберём три признака того, что POM у вас сломан.

Антипаттерн 1: God Page Object // ❌ Всё в одном классе class CheckoutPage { async fillShippingAddress() {} async fillBillingAddress() {} async applyPromoCode() {} async selectDeliveryMethod() {} async fillCardDetails() {} async submitOrder() {} // ... ещё 35 методов }

Когда в одном классе 40+ методов — это не абстракция, это свалка. Решение: разбить на ShippingForm, PaymentForm, OrderSummary.

Антипаттерн 2: expect внутри Page Object // ❌ PO решает, что правильно async submitAndVerify() { await this.submitBtn.click(); await expect(this.successMsg).toBeVisible(); // не сюда }

// ✅ Ассерты остаются в тесте async submit() { await this.submitBtn.click(); } // В тесте: await expect(page.checkoutPage.successMsg).toBeVisible()

Ассерты в PO скрывают намерения теста и нарушают SRP. Тест должен читаться как сценарий — «что происходит», а не «что проверяется внутри метода».

Антипаттерн 3: Leaky abstraction

Когда ProductPage.getPrice() возвращает Locator вместо string — абстракция течёт. Тест знает о реализации и привязывается к DOM.

Альтернативы: — Component Objects для переиспользуемых UI-блоков (хедер, модалки, таблицы) — Screenplay pattern если у вас сложная доменная логика — Просто fixtures + helper functions для небольших проектов — POM иногда избыточен

Правило, которого я придерживаюсь: если Page Object сложнее, чем код, который он тестирует — что-то пошло не так.

Как вы структурируете Page Objects в больших проектах? Есть ли у вас правило по размеру класса или количеству методов?

#typescript #playwright #architecture #sdet #qa_automation #automation @haradkou_sdet