Практичная упаковка тестового кода в модульном проекте - PullRequest
0 голосов
/ 14 января 2020

Я размышлял над модульной системой Java и у меня возник вопрос, который я не нашел здесь. Я еще немного покопался и обдумал ответ, так что, думаю, я опубликую информацию, если она сокращает чей-либо поиск.

Традиционно тесты хранятся в отдельном дереве исходных текстов от основного тела. кода проекта, поэтому двоичные файлы теста легко отделить от конечного конечного результата проекта. Я не был уверен, как добиться этого с модульной системой, но оказывается, что это все еще просто.

Наши источники для (потенциально многомодульных) модульных проектов обычно выкладываются примерно так: "sources/MyModule/src/main/java". Затем мы задали бы компиляцию, используя --module-source-path, установленный на "source/*/src/main/java" (обратите внимание, что кавычки важны, или ваша ОС попытается расширить звездочку. Вы не хотите этого, вы хотите передать ее javac). И если в исходном коде есть другие модули, при условии, что они имеют одинаковую общую структуру, отличающуюся только именами, они будут найдены и скомпилированы. Но, оказывается, мы можем разделить модуль на два дерева. Итак, этот исходный макет:

.
└── sources
    ├── ModOne
    │   ├── java
    │   │   ├── module-info.java
    │   │   └── pkg
    │   │       └── Prod.java
    │   └── test
    │       └── pkg
    │           └── Test.java
    └── ModTwo
        └── java
            ├── module-info.java
            └── p2
                └── RunMe.java

Компилируется правильно в одну go с помощью этой команды: javac -d out --module-source-path "./sources/*/java:./sources/*/test" --module ModTwo,ModOne Обратите внимание, я не указываю ModOne, тестовая часть не компилируется, но пока я сделать это явно, он найден, и выходные данные создали это дерево каталогов:

.
├── out
│   ├── ModOne
│   │   ├── module-info.class
│   │   └── pkg
│   │       ├── Prod.class
│   │       └── Test.class
│   └── ModTwo
│       ├── module-info.class
│       └── p2
│           └── RunMe.class

Основной метод в RunMe выполняется следующим образом: java --module-path out --module ModTwo/p2.RunMe и в моем классе Test есть main, который запускается и успешно имеет доступ на уровне пакета к остальной части кода ModOne.

Содержимое исходных файлов в деревьях:

sources/ModOne/java/module-info.java: 
module ModOne {
  exports pkg;
}

sources/ModOne/java/pkg/Prod.java:
package pkg;
public class Prod {
  public static String name = "Fred";
}

sources/ModOne/test/pkg/Test.java:
package pkg;
public class Test {
  public static void main(String [] args) {
    System.out.println("Value is " + Prod.name);
  }
}

sources/ModTwo/java/module-info.java:
module ModTwo {
  requires ModOne;
}

sources/ModTwo/java/p2/RunMe.java:
package p2;
public class RunMe {
  public static void main(String [] args) {
    System.out.println("Pulling from ModOne I get name is " + pkg.Prod.name);
  }
}

1 Ответ

0 голосов
/ 15 января 2020

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

Я сделал это Пример использования моего основного примера в недавней презентации под названием «Tweak Your Modules»:

В двух словах:

  1. Для main & test требуется две компиляции с разными параметрами
  2. Подключение зависимостей выполняется с помощью таких параметров, как --patch-module, --add-reads et c.

Хорошая новость: такие инструменты, как Maven или Eclipse, делают большую часть этого автоматически.

...