Интегрируем YAML и тестовый фреймворк
Новая заметка, в которой я покажу, как можно использовать файлы с разширением .yml в качестве конфигурационых файлов для тестового фреймворка. Хочу отметить, что я уже писал на подобную тему, только тогда применял Groovy файл.
Давайте посмотрим на суть задачи. Наверняка те, кто писал фреймворки на Java, пользовался стандартными файлами c расширением .proprties. Наличие проперти файлов - это правило хорошего тона.
Вся конфигурационная информация выносится за переделы кода, откуда ее можно легко изменять. Вот, скажем, стандартный пример из жизни: у нас есть несколько окружений, на которых мы запускаем наши тесты. Для каждого окружения нужны различные парметры: хост, порт и т.п. Зачастую люди делают либо разные проперти файлы и пишут Factory pattern для того, чтобы считывать из них информацию, либо делают один проперти файл, который зачастую выглядит так:
#dev env
dev.server.host=localhost
dev.server.port=7070
#qa env
qa.server.host=qahost
qa.server.port=8081
Затем пишется все та же Factory для считывания данного файла. Чего греха таить, я, бывало, тоже такое писал. Но пришло время совершенствоваться и использовать более элегантные подходы. И здесь на помощь приходит язык разметки YAML. Что это и для чего придумано, читать в Википедии ;)
Мы можем легко и просто использовать .yml файлы как замену для проперти файлов c помощью библиотеки snakeyml.
Создаем config.yml файл:
environment:
dev:
server.host: http://localhost:7070
db.url: jdbc:usernarm:userpass@test
qa:
server.host: http://qa.test:8080
Теперь напишем класс, который будет считывать наш файл:
public class YamlReader {
public Map<String, Object> read(String path) throws IOException {
InputStream in = Files.newInputStream(Paths.get(path));
Yaml yaml = new Yaml();
return (Map<String, Object>) yaml.load(in);
}
}
Читаем файл:
public static void main(String[] args) throws IOException {
YamlReader reader = new YamlReader();
Map<String, Object> config = reader.read("src/main/resources/config.yml");
System.out.println(config);
}
Console output:
{environment={dev={server.host=http://localhost:7070, db.url=jdbc:usernarm:userpass@test}, qa={server.host=http://qa.test:8080}}}
Нам возвращается Map, с которой мы можем дальше работать. Но здесь есть один недостаток - casting. Нам нужно кастить каждый раз, когда мы будем доставать значение из map.
Есть гораздо лучшее решение. Cоздаем класс Configuration следующего содержания:
public class Configuration {
public Map<String,Map<String,String>> environment;
}
Создаем метод в ридере:
public <T> T read(String path, Class<T> c) throws IOException {
Yaml yaml = new Yaml();
try (InputStream in = Files.newInputStream(Paths.get(path))) {
return yaml.loadAs(in, c);
}
}
Используем новый метод для чтения проперти:
YamlReader reader = new YamlReader();
Configuration read = reader.read("src/main/resources/config.yml", Configuration.class);
Map<String, String> map = read.environment.get("qa");
Как вы могли заметить, второй подход более элегантен и удобен. Правда, вы не сможете использовать никакой другой конструкции, кроме Map; в первом же случае вы вольны кастить значения к тому типу, к которому душе угодно. На этом у меня все. Подписывайтесь, чтобы держать руку на пульсе.