Использование констант для пунктов меню - оправдано ли?

Здравствуйте.
У меня возник спор с коллегой на счет того, каким образом делать открытие пунктов меню.

Я все пункты вывел в константы, пусть не сразу поймешь в тесте, что это константа означает (на англ иногда сложно перевести эти пункты), иногда они имеют длинные имена, но можно ведь перейти и прочитать что она означает, зато мы уверены что не посадили ошибку, не используя стринг напрямую.

Он же говорит, что константы не дают наглядности, что это лишнее звено и что пункты надо копировать каждый раз из браузера.

Вот я не могу понять… Неужели его предложение логичное?

Вот пример использования констант в тесте:

private void request4InclApprove() throws Exception {
    this.mainPage = this.loginPage.enter(this.host, this.loginFK, this.passFK);
    this.mainPage
            .openFormular(MenuNodes.APPROVE_REQUESTS)
            .selectDocumentInScroll(Status.IN_APPROVE)
            .toApprove()
            .checkStatusDocument(Status.APPROVED)
            .exit();

Использование констант более чем оправдано, и не только потому что это удобно и нельзя сделать ошибку, а еще и с точки зрения поддержки. При изменении текста необходимо будет заменить только один фрагмент кода и не искать по всему проекту данные. Решение в этом случае - делайте имена констант более длинными и содержательными, если начальству не нравятся короткие и немногословные.

1 лайк

Константы - это правильное решение. Более того, я бы предложил ещё 1 уровень абстракции: сгруппировать все эти константы в property файл.
Из плюсов - не будет требоваться менять код тестов, если изменится какое-либо название в менюшках. Кроме того, всегда знаешь, где нужно изменить, не надо лазить по классам и искать, в каком из них живёт данная константа.

1 лайк

Вы знаете, большинство ответит вам, что правильно использовать константы, да ещё и посоветуют вынести всё в файлы, эксельки, “карточки”, базу данных. Автоматизаторы любят всё усложнять. :slight_smile:

А я думаю, что словах вашего коллеги есть рациональное зерно.
Вообще-то ответ зависит от того, в скольких местах используется это значение (например, MenuNodes.APPROVE_REQUESTS). Если оно используется в одном месте, то незачем выносить его в константу.

А если оно используется во многих местах, то есть смысл вынестив константу, потому что в будущем менять значение придётся в одном месте.

НО
если оно используется во многих местах, у меня встаёт большой вопрос, а правильно ли вообще организованы ваши тесты?

1 лайк

На чем именно основано данное допущение?

1 лайк

Вообще-то это не допущение, это вопрос.
Ну как, в правильно организованных тестах один и тот же элемент не должен дёргаться много раз. Ну один, ну два, ну три. А если у вас сотни тестов многократно заполняют одну и ту же форму, это же очевидная пустая трата времени! Надо избавляться от дубликации.

1 лайк

Так разговор ведь не о формах. Меню - это ключевой компонент любого веб приложения. И вполне логично, что многие тесты могут дергать одни и те же элементы меню для прохода по определенным участкам в совершенно разных сценариях.

У меня возникает встречный вопрос - от чего собственно тут избавляться? Приложения бывают разные, ровно как и взаимосвязи между компонентами посредством меню. И я могу с ходу привести несколько популярных кейсов, когда вариант прямой навигации куда-либо, чтобы скипнуть часть якобы “неважного” функционала, совершенно не будет работать. Так что, как говорится, depends on… Вариант с константами выглядит вполне адекватным, как по мне.

3 лайка

Ну конечно it depends.
Поэтому это и был просто вопрос. Но вопрос очень даже оправданный, потому что очень часто в тестах делается много лишних шагов , повторений и т.д. Это ж прям беда индустрии!

1 лайк

Использую константы в своих тестах, очень удобный подход, пишу как-то так (небольшая часть):

public class Constants {

    public static final String BASE_DIRECTORY   = System.getProperty("user.dir");
    public static final String DS                  = System.getProperty("file.separator");
    public static final String MAIN_RESOURCES      = BASE_DIRECTORY + DS + "src" + DS + "main" + DS + "resources";
    public static final String TEST_RESOURCES      = BASE_DIRECTORY + DS + "src" + DS + "test" + DS + "resources";
    public static final String DIRECTORY_TEST_FILE = TEST_RESOURCES + DS + "files" + DS;

    public static class Settings {
        public static final String LOGS_DIRECTORY       = BASE_DIRECTORY + DS + "logs" + DS;
        public static final String SCREENSHOT_DIRECTORY = BASE_DIRECTORY + DS + "screenshots";
        public static final String DEFAULT_DATE_FORMAT  = "MMM dd, yyyy - hh:mm:ss a";

        public static class TestService {
            public static final String TEST_MAIL_SERVICE = "@mailinator.com";
        }
    }

    public static class Url {
        public static final String BASE_URL        = SystemProperty.BASE_URL.getValue();
        public static final String CP_BASE_URL     = SystemProperty.CP_BASE_URL.getValue();
        public static final String DEMO_BASE_URL   = SystemProperty.DEMO_BASE_URL.getValue();
    }

    public static class TestData {

        public static class Email {
            public static final String QA_EMAIL      = "qa@foobar.com";
            public static final String JENKINS_EMAIL = "jenkins@foobar.com";
            public static final String DEBUG_EMAIL = "debug@foobar.com";
        }
    }
}

а вызываю как-то так:

Constants.TestData.Email.JENKINS_EMAIL

вроде наглядно в тестах получается, как по мне… Поэтому думаю, что для пунктов меню очень даже оправдано и даже для тестовых карточек, которые не меняются и используются в разных тестах…

Использую так, потому что мне это удобно… Если бы было неудобно, то я бы писал отдельную стрингу в каждом тесте. Для того, чтобы это еще было и читаемо, закидываю в разные подклассы и получаются записи такого вида:

Constants.TestData.Email.JENKINS_EMAIL
Constants.PurchaseData.PayPal.TEST_FIRST_NAME
Constants.PurchaseData.PayPal.TEST_LAST_NAME
Constants.PurchaseData.PayPal.TEST_COUNTRY
Constants.PurchaseData.PayPal.TEST_ADDRESS1
Constants.PurchaseData.PayPal.TEST_REGION

походу так многие делают

2 лайка

Вы меня простите, но это тихий ужас. Ведь это можно гораздо короче написать.
Я ещё понимаю, что QA_EMAIL выделено в константу. Это ок.

Но все эти заморочки в путями…
Как минимум синтаксис можно укоротить:

public class Constants {
    public static final String BASE_DIRECTORY   = System.getProperty("user.dir");
    public static final String MAIN_RESOURCES  = "src/main/resources";
    public static final String TEST_RESOURCES  = "src/test/resources";
    public static final String DIRECTORY_TEST_FILE = "src/test/resources/files";

    public static class Settings {
        public static final String LOGS_DIRECTORY       = "logs";
        public static final String SCREENSHOT_DIRECTORY = "screenshots";
    }

И будет точно так же работать!

Но это не самое главное. Важнее вопрос - зачем вам вообще эти константы? Зачем, скажем, путь к src/test/resources? Все эти файлы будут доступны через classpath.

Дальше, зачем вам константа DEFAULT_DATE_FORMAT?
Все места в коде, которые её используют, будут совершенно одинаковыми. Они все делают new SimpleDateFormat(DEFAULT_DATE_FORMAT) и либо парсят, либо форматируют дату. Так? Значит, надо константу сделать приватной, и добавить пару публичных методов для парсинга/форматирования даты.

да это кусок из старого примерчика, что под рукой оказалось на личном компе

  1. для путей вы правы, полностью с вами соглашусь, и недавно уже даже переделал, как вы выше написали, и их уже нет в константах
  2. для “DEFAULT_DATE_FORMAT” у меня во всех проектах везде один формат даты выводится (так сложилось), и я сделал два метода в котором указал стандартный и перегрузил метод для того, чтобы указать кастомный… Не знаю, удобно мне так зайти в константы и заменить там дефолтную дату, оно поменяет везде, если в проекте изменится, нежели идти в метод с датой. Так удобней мне, я думал об этом ранее

вроде как есть логика в ваших словах, но когда проект расширяется и над ним начинают работать больше одного человека, и приходят новые, то наверное проще зайти в константы и там подсмотреть или поменять

Не понял.
Так метод-то будет здесь же, в этом же классе! Забавно: выносите значение в константы, но при этом копипаст из всех дыр торчит.

Выносить надо не константы, а логику работы с ними. Вот в чём смысл инкапсуляции.