While working on a laravel 5.1+ package I have this need to run automated tests through travis-ci.org. The difference with regular automated tests is the requirement to include this package into a framework and set specific configuration options to run the tests.
So the requirement would be:
install laravel
add my package as dependency
set some travis specific configurations like the travis database access
run migrations of laravel
run migrations specific for package or run an artisan command
run package specific unit tests
I searched everywhere; asked on laravel forums, asked in a travis community chat and saw this topic being closed as too localized (although an answer would have certainly been helpful now). I'm hoping my question is fit to remain open.
At this time I have the following configuration:
language: php
php:
- 5.5
- 5.6
- hhvm
addons:
hosts:
- system.hyn.me
- tenant.hyn.me
before_install:
- sudo composer self-update
install:
- composer create-project laravel/laravel
- cd ./laravel
- composer require hyn-me/multi-tenant ~0.1.0
- composer update
before_script:
- cp .env.travis .env
- export APP_ENV="testing"
- php artisan migrate -q -n --path ./vendor/hyn-me/multi-tenant/src/migrations
- cd ./vendor/hyn-me/multi-tenant
script: phpunit
Yet my knowledge of travis (thus far) is limited and before I send in an unneeded number of commits to fix my problems I'd rather have your opinion on what would be a good method to test integration into a framework.
Ps. this concerns the package hyn/multi-tenant.
Advise on how to keep this question as generic as possible would be helpful. I hope without explicitly mentioning best practice and requesting integration into framework examples helps in defining the scope of the answers.
So after weeks of pushing commits into travis, I finally made this work.
The .travis.yml:
language: php
sudo: true
php:
- 5.5
- 5.6
- 7.0
- hhvm
addons:
hosts:
- system.hyn.me
- tenant.hyn.me
install:
# fix ipv6 issue that prevented composer requests and resulted in failing builds
- sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf"
# updates composer on travis
- travis_retry composer self-update
# clear composer cache, might speed up finding new tags
- travis_retry composer clear-cache
# set the global github token, so connections won't be cancelled
- composer config -g github-oauth.github.com $GITHUB_TOKEN
# create a new database for the hyn connection
- mysql -e 'create database hyn;' -uroot
- mysql -e "grant all privileges on *.* to 'travis'#'localhost' with grant option;" -uroot
# create a new laravel project in the subfolder laravel (default composer behaviour)
- composer create-project laravel/laravel
# set global variables
- export DB_USERNAME=travis DB_DATABASE=hyn DB_PASSWORD= QUEUE_DRIVER=sync
script:
# run the script calling unit tests and so on
- ./scripts/travis.sh
after_script:
- if [[ $TRAVIS_PHP_VERSION != '7.0' ]]; then php vendor/bin/ocular code-coverage:upload --format=php-clover ${TRAVIS_BUILD_DIR}/coverage.clover; fi
And the scripts/travis.sh
#!/bin/bash
# e causes to exit when one commands returns non-zero
# v prints every line before executing
set -ev
cd ${TRAVIS_BUILD_DIR}/laravel
BRANCH_REGEX="^(([[:digit:]]+\.)+[[:digit:]]+)$"
if [[ ${TRAVIS_BRANCH} =~ $BRANCH_REGEX ]]; then
echo "composer require ${TRAVIS_REPO_SLUG}:${TRAVIS_BRANCH}"
composer require ${TRAVIS_REPO_SLUG}:${TRAVIS_BRANCH}
else
echo "composer require ${TRAVIS_REPO_SLUG}:dev-${TRAVIS_BRANCH}"
# development package of framework could be required for the package
composer require hyn-me/framework "dev-master as 0.1.99"
composer require "${TRAVIS_REPO_SLUG}:dev-${TRAVIS_BRANCH}#${TRAVIS_COMMIT}"
fi
# moves the unit test to the root laravel directory
cp ./vendor/${TRAVIS_REPO_SLUG}/phpunit.travis.xml ./phpunit.xml
phpunit
# phpunit --coverage-text --coverage-clover=${TRAVIS_BUILD_DIR}/coverage.clover
This code might change due to new Laravel versions or changes in travis. If this is the case, you will find the latest release here.
Related
I want to use travis with my simple php projects. My project structure is next:
My .travis.yml
language: php
sudo: required
before_install:
- cd http
before_script:
- cd http
install:
- composer self-update
- composer-install --no-interaction
script:
- phpunit --configuration phpunit.xml
and I want to run trevis into http folder, my composer.json and phpunit are there. However, as a result of my build, I received:
How can I solve this issue and run travis correctly? Thanks
A little context: I am new to docker and dont know of any best-practices yet. My task is to create a webservice based on php and i decided to use docker-compose for provisioning.
Because we are all fancy devs, we know - there is no way to build a php application without using composer these days.
My question:
Should i install dependencies in the build? So by adding this to my Dockerfile:
RUN cd /app && composer install --no-interaction --prefer-source --optimize-autoloader
Or should i install dependencies during development and build the container image with included dependencies?
I only know of one way NOT to do it: install dependencies locally on the dev machine and build the container afterwards. But how would the "best practice" look like?
And - because i am a newbee in this field - how would i run a "composer require some/package" for my app service container?
By the way
I also noticed a message "Do not run Composer as root/super user!" when building the container. I added COMPOSER_ALLOW_SUPERUSER=1 to my Env file (as seen here), but this message still appears.
Is it possible to NOT execute composer install as root in a docker container? Can i ignore that message?
Thanks in advance,
Philipp
For the moment i am working towards the following solutuion:
Development environment:
Add the whole src as volume:
volumes:
- .:/app
initial composer install command
docker-compose exec app composer install
install new composer package:
docker-compose exec app composer require some/package
The package will be installed via the container in your composer package directory (/vendor by default of course), the source code can be inspected in your ide, etc.
Production environment:
Only app state defined as volume, for example:
volumes:
- public/uploads:/app/public/uploads
add /vendor to .dockerignore
and run composer install during build
RUN cd /app && composer install --no-dev --no-interaction --optimize-autoloader
So you will have a pre-built image to deploy, but still be able to develop in a more agile way.
There are still two downsides in this solution, maybe someone has input for me:
1) build becomes kind of slow - it seems composer caching does not work properly
A solution (i dont know if this is possible in composer) could be a volume for the composer cache directory.
2) all packages created by docker are owned by root, so you can only work on those files/folders with sudo/root session.
I have no idea how to fix this properly. Maybe i could create a user with the name of the dev user for the development container and have this user run commands and php-fpm, etc... For production root would be okay i guess.
I am still very new to docker and open for better solutions, so i wont accept this answer.
UPDATED
To add new user in docker user in Dockerfile. as follows
RUN useradd -ms /bin/bash newuser
USER newuser
if you want to create home user too
WORKDIR /home/newuser
or
mkdir /home/newuser
if you want to back to root user, you can do like
USER root
two-sides-of-a-coin -
It is a good practice to do on building images period which I also do the same as you.
we will get latest update from public repositories but another side of coin is that we cannot ensure they are the same version as we develop.
you need to handle this by specifying exact version in composer.json (do not use ^, *).
On every travis build, composer self-update is run. And it gets updated on every build. Is it possible to cache composer executables like we do it with vendor dir via
cache:
directories:
- vendor
- $HOME/.composer/cache
I thought about caching the whole /home/travis/.phpenv/versions/5.5/bin/composer but I feel this is not right because the contents of this folder may change without notifying caching system about a change (when travis updates php version for example).
Any suggestions (except for custom composer, of course)?
I'd recommend not updating composer itself, but let travis handle it. (its automatically updated every 30/60 days)
Also i can recommend using the new containerized infrastructure to speed up the runs and allow caching...
language: php
sudo: false
cache:
directories:
- $HOME/.composer/cache
php:
- 5.5
- 5.6
- 7
- hhvm
install:
- composer install
script: vendor/bin/phpunit
The sudo: false statement indicates the use of containers. The cache: statement makes sure composer caches correctly.
If you really want to cache the composer binary:
language: php
php:
- 5.5
- 5.6
- 7
- hhvm
cache:
directories:
- $HOME/.composer/cache
install:
- travis_retry composer self-update && composer --version
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- travis_retry composer install --prefer-dist --no-interaction
script: vendor/bin/phpunit
Also just as a heads up, if testing for HHVM and you need to set the datetime, have a look at https://github.com/travis-ci/travis-ci/issues/2523. My way of solving this is adding a .ini-file in my test-directory with the datetime and setting this in the correct folder for all test-runners. This is prepended in the install:-step:
- mkdir -p /home/travis/.phpenv/versions/$(phpenv version-name)/etc/conf.d
- phpenv config-add test/phpconfig.ini
Anyway, a bit more information than you requested, but i hope this helps someone looking for composer/travis/stuff :)
I just installed a fresh Laravel 5 project, my first one on this version. PHPUnit is supposed to be out of the box with the framework and every tutorials I saw just say to type phpunit within the project folder to launch the Unit Tests.
I checked and PHPUnit is in the composer.json, I also did a composer install and composer update just in case it wouldn't be here
website(master)$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Removing phpunit/phpunit (4.6.1)
- Installing phpunit/phpunit (4.6.2)
Downloading: 100%
But it just doesn't work phpunit isn't recognized at all
website(master)$ phpunit
-bash: phpunit: command not found
Seems like nobody got this problem before as I Googled it. I hope I'm not doing any stupid mistake. Any idea or suggestion ? Thanks guys ;)
I didn't install PHPUnit globally and didn't define the path. So for anyone who would have same problem :
composer global require phpunit/phpunit
composer global require phpunit/dbunit
Then you add this to you ~/.bash_profile or ~/.profile
export PATH=~/.composer/vendor/bin:$PATH
This occurs when you don't have phpunit installed globally.
Run this command to use the local version (installed with composer):
vendor/bin/phpunit
in windows machine the command is different please use this command
php vendor/phpunit/phpunit/phpunit
orignal source
You can run this command in cmd before running phpunit command:
doskey phpunit="vendor/bin/phpunit"
And if you are lazy as I am, you can run this one:
doskey pu="vendor/bin/phpunit"
for people who have WINDOWS 7, use the .\vendor\bin\phpunit command instead of ./vendor/bin/phpunit
Run the command
composer config --list --global | grep -w home
You can find the find the [home] with composer path, similar to this one.
[home] /home/example_username/.config/composer
The path ~/.config/composer is where composer global packages are installed. Next run the command...
export PATH=~/.config/composer/vendor/bin:$PATH
I made a permanent link to my phpunit like this
echo 'alias phpunit=vendor/bin/phpunit' >> ~/.bash_aliases
now phpunit is working by itself and stays even after I restart the terminal
Include this line on your composer.json
"phpunit/phpunit": "4.0.*",
Run composer update.
You should be able to run the following command on your Laravel directory.
vendor/bin/phpunit
I'm using Homestead to serve my Laravel application. I'm trying to run PHPUnit. According to the docs:
An example test file is provided in the app/tests directory. After
installing a new Laravel application, simply run phpunit on the
command line to run your tests.
Well, when I'm "simply running" phpunit in my project root (inside the Homestead environment) I get this:
The program 'phpunit' is currently not installed.
Do I need to install PHPUnit separately then? The documentation does not mention it. What am I doing wrong?
You can install it globally on the system using.
composer global require phpunit/phpunit
However, if you need different versions for different projects this can cause issues.
The alternative option is to use the version installed as part of your dependencies by referencing the path to your vendor directory.
./vendor/bin/phpunit
You could even add an alias to your aliases file in your ~/Homestead directory. That way you're always using the phpunit version that is installed with your project dependencies.
alias phpunit=./vendor/bin/phpunit
You'll need to restart the homestead box to make use of the alias.
You can install it globally with:
$ composer global require "phpunit/phpunit=4.4.*"
# then use
$ phpunit
or you can use it with your local composer:
$ composer require "phpunit/phpunit=4.4.*"
# then
$ vendor/bin/phpunit
Since it's a package required for development, Laravel provide PHPunit(require-dev section in composer), you should find it in vendor's folder :
$ your_app/vendor/bin/
You can run the command from the root of your app folder by typing :
$ vendor/bin/phpunit
I hope it will help !