Over the past year, we have developed four plug-ins for the Redmine + Telegram bundle ( one , two , three , four ).
Quietly, their Best Practices are developed for them. In this article we will talk about testing and integration with Travis CI .
Habitual rspec from the first approach could not screw. From the second and third too.
Examples of plug-ins with good test coverage also could not be found. Most plug-ins are either completely without tests, or the plug-ins themselves are so simple that the tests for them were placed in one file. As a rule, these were tests for views. And we need to test the logic.
The best example was the tests of Redmine itself. In this project, the usual rails default tests are used without any minor design ( proof ).
The lack of contexts within the same test makes it difficult to test different situations for the same class. Therefore, direct adherence to this approach once led us to a dead end.
Very helpful from the 2011 edition of the Rails Test Prescription book. From it we learned about how to write Rails default style tests, and also about the hem shoulda , which became our salvation.
Examples will be given from the redmine_2fa plugin, which we announced last month. And also from the new redmine_telegram_common , about which we will also tell one day.
Tests run and root Redmine:
bundle exec rake redmine:plugins:test NAME=redmine_2fa
On the version of Redmine 3.3.1, when executing this command, there are a lot of ruby test_helper.rb
in order to make the issue cleaner, add the following line to test_helper.rb
:
$VERBOSE = nil # for hide ruby warnings
To use your fixtures in tests, you need to add the same file
ActiveRecord::FixtureSet.create_fixtures(File.dirname(__FILE__) + '/fixtures/', [:auth_sources])
Where instead of :auth_sources
will be those fixtures that need to be loaded to the tests.
group :test do gem 'shoulda' end
shoulda is a must have gem for testing plugins. The rest - depending on the needs for testing.
class AccountControllerPatchTest < ActionController::TestCase # tests AccountController # fixtures :users, :email_addresses, :roles, :auth_sources # setup do @user = User.find(2) # jsmith Redmine2FA.stubs(:active_protocols).returns(Redmine2FA::AVAILABLE_PROTOCOLS) end # context 'user without 2fa' do context 'with valid login data' do setup { post :login, username: 'jsmith', password: 'jsmith', back_url: 'http://test.host/' } context 'prepare' do should set_session[:otp_user_id].to(2) should set_session[:otp_back_url].to('http://test.host/') should 'set user instance variable' do assert_equal @user, assigns(:user) end end end end
New did not look, we use the heme mocha that is used in Redmine.
Examples of using:
User.any_instance.stubs(:mobile_phone).returns('7894561230') User.any_instance.expects(:authenticate_otp).returns(true)
Tests for routes are located in the integration/routing
folder.
Redmine has its own helpers for testing:
should_route 'POST /redmine_2fa/bot/init' => 'otp_bot#create'
But for difficult routes, you need to use a rail helper:
assert_routing({ method: 'post', path: '/redmine_2fa/bot/token:token/update' }, controller: 'otp_bot_webhook', action: 'update', token: 'token:token')
They do not make sense to describe in detail let's do a small example:
context 'confirmation' do setup do User.any_instance.stubs(:mobile_phone).returns('79243216547') end should 'confirm mobile phone with valid code' do User.any_instance.expects(:authenticate_otp).returns(true) @user.confirm_mobile_phone('valid') @user.reload assert @user.mobile_phone_confirmed? end should 'return errors with invalid code' do User.any_instance.expects(:authenticate_otp).returns(false) @user.confirm_mobile_phone('invalid') @user.reload assert !@user.mobile_phone_confirmed? assert @user.errors.present? end end
As you remember from the beginning of the article, plug-in tests are run from the Redmine root. And the code of the Redmine plugin itself does not contain.
Therefore, in the testing process you need to include the installation of Redmine, the initialization of its base and only then the launch of tests.
language: ruby rvm: - 2.3.0 addons: postgresql: "9.4" env: - REDMINE_VER=3.3-stable - REDMINE_VER=master install: "echo skip bundle install" before_script: - psql -c 'create database travis_ci_test;' -U postgres script: - export TESTSPACE=`pwd`/testspace - export NAME_OF_PLUGIN=redmine_telegram_common - export PATH_TO_PLUGIN=`pwd` - export PATH_TO_REDMINE=$TESTSPACE/redmine - mkdir $TESTSPACE - cp test/support/* $TESTSPACE/ - bash -x ./travis.sh
In install
costs
install: "echo skip bundle install"
because the basic setup logic is run in a script
bash -x ./travis.sh
#/bin/bash set -e if [[ ! "$TESTSPACE" = /* ]] || [[ ! "$PATH_TO_REDMINE" = /* ]] || [[ ! "$REDMINE_VER" = * ]] || [[ ! "$NAME_OF_PLUGIN" = * ]] || [[ ! "$PATH_TO_PLUGIN" = /* ]]; then echo "You should set"\ " TESTSPACE, PATH_TO_REDMINE, REDMINE_VER"\ " NAME_OF_PLUGIN, PATH_TO_PLUGIN"\ " environment variables" echo "You set:"\ "$TESTSPACE"\ "$PATH_TO_REDMINE"\ "$REDMINE_VER"\ "$NAME_OF_PLUGIN"\ "$PATH_TO_PLUGIN" exit 1; fi export RAILS_ENV=test export REDMINE_GIT_REPO=git://github.com/redmine/redmine.git export REDMINE_GIT_TAG=$REDMINE_VER export BUNDLE_GEMFILE=$PATH_TO_REDMINE/Gemfile # checkout redmine git clone $REDMINE_GIT_REPO $PATH_TO_REDMINE cd $PATH_TO_REDMINE if [ ! "$REDMINE_GIT_TAG" = "master" ]; then git checkout -b $REDMINE_GIT_TAG origin/$REDMINE_GIT_TAG fi mv $TESTSPACE/database.yml.travis config/database.yml mv $TESTSPACE/additional_environment.rb config/ # create a link to the backlogs plugin ln -sf $PATH_TO_PLUGIN plugins/$NAME_OF_PLUGIN # install gems bundle install # run redmine database migrations bundle exec rake db:migrate # run plugin database migrations bundle exec rake redmine:plugins:migrate bundle exec rake db:structure:dump # run tests bundle exec rake redmine:plugins:test NAME=$NAME_OF_PLUGIN
If you use this script, the test database configuration should be placed in the file test/support/database.yml.travis
test: adapter: postgresql encoding: unicode pool: 5 database: travis_ci_test user: postgres
Short on the main points walked. About the details and details - continue in the comments. More examples for tests - in the source code redmine_2fa and redmine_telegram_common .
Source: https://habr.com/ru/post/314954/