Проверьте, существует ли внутренний класс с RSpe c и PDK - PullRequest
1 голос
/ 20 января 2020

У меня есть довольно базовый c кукольный модуль для веб-сервиса под управлением tomcat. Я хочу настроить logrotate для файла Tomcat catalina.out и начать с написания теста, который подтверждает, что logrotate включен в модуль и настроен с правильными настройками.

Вот урезанная версия моего webservice.pp, например:

class my_module::webservice (
  ...
){
  include ::tomcat_server

  ...

  logrotate::rule { 'tomcat':
    path          => '/var/log/tomcat/catalina.out',
    rotate        => 1,
    rotate_every  => 'day',
    copytruncate  => true,
    missingok     => true,
    compress      => true,
    delaycompress => true,
  }
}

, и я включил модуль кузницы logrotate в мой .fixtures.yml примерно так:

fixtures:
  forge_modules:
    logrotate:
      repo: 'puppet-logrotate'
      ref:  '3.2.1'
    ...

Но я могу написать только тест, который подтверждает, что logrotate включен в модуль следующим образом:

require 'spec_helper'

describe 'my_module::webservice' do
  on_supported_os.each do |os, os_facts|
    context "on #{os}" do
      let(:facts) { os_facts }

      it { is_expected.to compile }

      it { is_expected.to contain_class('logrotate') }
    end
  end
end

Это не работает (если я удаляю блок logrotate из init.pp, тогда тесты все еще проходят):

it { is_expected.to contain_class('logrotate::conf') }

также не запрашивает with:

it { is_expected.to contain_class('logrotate') \
  .with('path'          => '/var/log/tomcat/catalina.out',
        'rotate'        => 1,
        'rotate_every'  => 'day',
        'copytruncate'  => true,
        'missingok'     => true,
        'compress'      => true,
        'delaycompress' => true,
  )
}

и не имеет отдельного / вложенного describe блока:

describe 'logrotate::rule' do
  let(:title) { 'tomcat' }
  let(:params) do
    {
        'path'          => '/var/log/tomcat/catalina.out',
        'rotate'        => 1,
        'rotate_every'  => 'day',
        'copytruncate'  => true,
        'missingok'     => true,
        'compress'      => true,
        'delaycompress' => true,
    }
  end
end

Я не могу найти ничего в rspe * Определено 1033 * документов, в которых упоминается что-либо кроме тестирования класса. Можно ли даже сделать то, что я пытаюсь сделать?

Вот мой макет каталога:

puppet
  `- modules
        `- my_module
             |- data
             |- manifests
             |    |- init.pp
             |    `- webservice.pp
             |- spec
             |    |- classes
             |    |    `- webservice_spec.rb
             |    `- spec_helper.rb
             |- .fixtures.yml
             |- Gemfile
             |- hiera.yaml
             |- metadata.json
             `- Rakefile

1 Ответ

3 голосов
/ 20 января 2020

У меня есть довольно базовый c кукольный модуль для веб-сервиса под управлением tomcat. Я хочу настроить logrotate в файле Tomcat catalina.out, и я хочу начать с написания теста, который подтверждает, что logrotate включен в модуль и настроен с правильными настройками.

Это звучит очень разумно. Однако, это ...

Вот урезанная версия моего init.pp, например:

class my_module::webservice (
  ...
){

... в лучшем случае плохая практика. Если он вообще существует, то манифест init.pp модуля my_module должен определять только класс my_module. Класс с именем my_module::webservice должен быть определен в манифесте с именем webservice.pp в модуле my_module. Ожидаемое расположение модулей задокументировано в онлайн-документации Puppet. Хотя вы, возможно, сможете избежать определенных расхождений с этими спецификациями, у этого есть только недостатки.

На данный момент я замечаю, что «внутренний класс» не является идиоматическим c Терминология кукол, и это предполагает недопонимание того, с чем вы работаете. В частности, этот ...

logrotate::rule { 'tomcat':

[...]

... вообще не объявляет класс , но вместо этого объявляется ресурс типа logrotate::rule, который, очевидно, является определенным типом, предоставляемым модулем puppet / logrotate. В общем, объявление ресурса не подразумевает ничего о классах из модуля (если есть), который предоставляет тип ресурса.

Кроме того, хотя вполне возможно, что объявление ресурса logrotate::rule действительно вызывает класс logrotate если он будет включен в каталог, это будет деталь реализации logrotate::rule, и поэтому ваши spe c тесты не должны его тестировать. Только если ожидается, что my_module::webservice сам объявит класс logrotate, если его тесты проверят это.

Вы go скажете:

Это не работает (если я удаляю блок logrotate из init.pp, тогда тесты по-прежнему проходят):

it { is_expected.to contain_class('logrotate::conf') }

Вы не предоставили достаточно кода, чтобы мы могли определить, почему тесты проходят, когда они включены в их, но что-то очень странное, если когда-либо это ожидание оправдается. logrotate::conf также является определенным (ресурсным) типом, а не классом, поэтому ожидание никогда не будет успешным. И, следуя теме, которую я представил выше, если класс my_module::webservice не объявляет какой-либо ресурс logrotate::conf напрямую, его тесты не должны проверять его на наличие.

и не запрашивать с помощью:

it { is_expected.to contain_class('logrotate') \
  .with('path'          => '/var/log/tomcat/catalina.out',
        'rotate'        => 1,
        'rotate_every'  => 'day',
        'copytruncate'  => true,
        'missingok'     => true,
        'compress'      => true,
        'delaycompress' => true,
  )
}

Конечно, это не удается. Он выражает ожидание объявления класса logrotate, но на самом деле вы объявили ресурс типа logrotate::rule. Даже если logrotate::rule объявит logrotate, никто не будет ожидать, что он передаст свой собственный список параметров.

, и при этом не будет отдельного / вложенного блока описания:

describe 'logrotate::rule' do

[...]

Опять же, это не удивительно. Такой describe блок сообщает RSpe c, что logrotate::rule является тестируемым классом. Это не только тестируемый класс (то есть, конечно, my_module::webservice), но, опять же, logrotate::rule вообще не является классом. RSpe c также может тестировать определенные типы, но это не то, что вам нужно.

Чтобы проверить, объявлен ли ресурс тестируемым классом , используется предикат вида contain_ тип ( title ), где любые разделители пространства имен (::) в имени типа заменяются двойными подчеркиваниями. Например:

it do
  is_expected.to contain_logrotate__rule('tomcat')
end

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

require 'spec_helper'

describe 'my_module::webservice' do
  on_supported_os.each do |os, os_facts|
    context "on #{os}" do
      let(:facts) { os_facts }

      it do
        is_expected.to compile
        is_expected.to contain_logrotate__rule('tomcat')
          .with(
            path: '/var/log/tomcat/catalina.out',
            rotate: 1,
            rotate_every: 'day',
            copytruncate: true,
            missingok: true,
            compress: true,
            delaycompress: true
          )
      end
    end
  end
end

Кстати, обратите внимание, что когда вы хотите проверить несколько предикатов на одном и том же примере, существенно эффективнее сгруппировать их в один блок it, как показано выше, чем помещать каждый в его собственный it блок. Например, вы, вероятно, заметите разницу во времени выполнения теста даже от объединения всего двух it блоков в один.

Кроме того, мой пример выше демонстрирует стиль кодирования, близкий к тому, который требуется, чтобы избежать предупреждений от pdk validate , что подводит нас к еще одному пункту: всегда полезно проверить, что pdk validate завершается без ошибок или предупреждений, прежде чем пытаться выполнить модульные тесты. Возможно, вы обнаружите, что он чрезмерно требователен как к Puppet, так и к стилю кода Ruby, но он также обнаружит некоторые проблемы, которые приводят к таинственным сбоям тестирования. Кроме того, он работает намного быстрее, чем тесты, и обнаружит практически все синтаксические ошибки как в коде Puppet, так и в Ruby. Расстраивает, что ваши тесты долго не срабатывают из-за незначительной синтаксической ошибки.

...