несколько «сетей» в связанных модулях OCaml - PullRequest
7 голосов
/ 02 апреля 2012

У меня есть несколько «библиотечных» модулей в OCaml (в основном, утилиты и вспомогательные функции), в которые я добавил следующий код для простейшего модульного тестирования:

let main () = ...
main

или

let () = ...

Это код, который в основном выводится на консоль (для простых целей тестирования).Проблема сейчас в том, что когда я связываю свои «библиотечные» модули с моим «основным» модулем и выполняю программу, я получаю все эти отвлекающие тестовые сообщения.Есть ли способ включить код в модуль OCaml, который исполняется, когда модуль связан отдельно (что облегчает тривиальное тестирование), но не при использовании в качестве «библиотеки»?Я читал посты в SO о том, что OCaml не имеет понятия «основной» модуль и что все модули равны, однако мне кажется, что порядок объектных файлов, передаваемых компоновщику, может быть истолкован, чтобы показать, чтопоследний модуль является «основным» (так как он находится на вершине «пищевой цепочки зависимостей»).

Ответы [ 2 ]

7 голосов
/ 02 апреля 2012

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

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

Так что, если вы ничего не делаете с этим, модуль не знает, с каким исполняемым файлом он каким-то «волшебным» образом связан; то, что вы должны сделать, imho:

  • перенести тесты из модулей, возможно, используя ounit ИЛИ
  • как минимум переписать ваши тестовые функции, чтобы они стали реальными функциями, например "let test () = ..."; затем напишите интерфейс тестирования, который будет вызывать все «тестовые» функции из всех ваших модулей.

дополнение:

Если вы сделаете это на других языках, то, кажется, бесплатного торта тоже не будет:

В Java, если у вас в коде несколько сетей, вы должны явно выбрать ту, которую вы хотите, чтобы исполняемый файл выполнялся.

В C вы можете использовать препроцессор C, чтобы сделать что-то вроде

#ifdef TEST_1
int main() {
...
}
#endif

OCaml имеет свой собственный препроцессор camlp4 ( camlp4 wikipedia article ), с которым вы можете сделать что-то подобное. Я лично считаю этот вид встраивания тестов плохой разработкой программного обеспечения. Вам лучше протестировать свой модуль / класс / .. со стороны интерфейса и пометить свои внутренние инварианты утверждениями (которые существуют в Java, C & OCaml).

5 голосов
/ 02 апреля 2012

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...