פעם שאלו אותי מה הפוסט הנישתי ביותר שאני יכול לכתוב באינטרנט ישראל. תמיד הייתי בטוח שהפוסט על כתיבת פונקצית נייטיב ב-SASS באמצעות רובי זה הדבר האיזוטרי ביותר שאפשר לכתוב. ועכשיו הגיע היום שבו אני אכתוב פוסט איזוטרי אף יותר. על מה אנחנו מדברים?
בפוסטים קודמים דיברתי על הרצת בדיקות אוטומטיות עם PHPUnit על תוספים של וורדפרס. אם אתם לא מפתחי וורדפרס, זה הרגע שבו אתם סוגרים את הדף הזה ומחכים למאמר יותר רלוונטי בשבוע הבא. סבבה.
מפתחי וורדפרס גם לא ממש יתעניינו. אם אתם מפתחי וורדפרס ולא קוראים לכם יקיר מ-pojo.me, סביר להניח שאתם זזים על הכסא באי נוחות. רוב מפתחי התוספים בעולם בכלל ובישראל בפרט, לא כותבים בדיקות אוטומטיות לתוספים שלהם. אתם יודעים שזה חשוב, אתם יודעים שזה כדאי מאוד ועדיין תשעים אחוז לא עושים את זה. אתם תגידו לעצמכם 'אה, הפוסט הזה מדבר על בדיקות אוטומטיות, זה חשוב, אני אחזור לזה מתישהו. כן, בשבוע הבא. אולי עוד שבועיים. אולי עוד חודש' ותסגרו את הדף ותחכו למאמר יותר רלוונטי בשבוע הבא. סבבה.
בפוסט לאחר מכן, דיברנו על הרצה של הבדיקות כחלק מבילד של Travis CI. מה זאת אומרת? שאם יש לי בדיקות אוטומטיות על התוסף והוא גם מאוכסן בגיטהאב, אני יכול לקשור אליו את Travis CI ולייצר תהליך שיריץ את כל הבדיקות האוטומטיות שלי. מה הבעיה? הבעיה היא שהמאמר יעניין אתכם רק אם אתם כותבים בדיקות אוטומטיות ואתם גם משתמשים ב-GitHub כבסיס לפיתוח שלכם (שזו הנחה מאוד משמעותית, כי מי שכותב מוצרים שמשתמשים בבדיקות אוטומטיות עושה את זה בדרך כלל עבור לקוחות שלא מוכנים לחשוף את המוצר שלהם החוצה). מי שלא, גם אם הוא כותב בכלים אוטומטיים יגיד לעצמו "טוב, זה נחמד, אבל בת'כלס יש לי build manager לדברים האלו והוא משתמש בכלל ב-jenkins'.
נשארנו עם ארבעה אנשים בערך. אחד מהם בכלל דרופליסט (אתה יודע מי אתה ואתה יודע שאני יודע מי אתה!), השני הוא יקיר שפשוט עושה ניטפיקינג ואת השניים האחרים אני לא מכיר. חבל. תתחברו אלי בפייסבוק ותגידו שלום 🙂 ועכשיו אגיע לשיא האיזוטריות! עכשיו אכתוב על איך אני עושה אינטגרציה של בדיקות ב-grunt יחד עם בדיקות PHPUnit ב-Travis CI. מה זאת אומרת? נניח שיש לי grunt שמריץ בדיקות תקינות על קוד ה-PHP ועל קוד ה-JS. איך אני אריץ אותו כחלק מ-Travis CI לאחר בדיקות ה-PHPUnit? אני רוצה ליצור מצב שאם הקוד לא כתוב בסטנדרטים, הבילד יפול. איך עושים את זה?
מי שלא זוכר מה זה סטנדרטים של קוד ואיך אוכפים אותם עם הסטנדרטים של וורדפרס, מוזמן למאמר הזה. אני גם יוצא מנקודת הנחה שאתם מכירים את Grunt.js. לפחות ברמה של יצירת משימות משלכם.
אז ראשית, אני אבנה grunt שיש בו משימות שמריצות את phpcs עם קונבנציות של וורדפרס. איך עושים את זה? מתקינים את grunt-phpcs ואת grunt-contrib-jshint באמצעות:
npm install grunt-phpcs --save npm install grunt-contrib-jshint --save
ה save– הוא קריטי. כיוון שמייד אחרי שאני מתקין אותם. אני צריך ליצור package.json. למי שלא מכיר node.js, ה-package.json מאפשר לכל אחד להתקין את המודולים שהתקנתי עכשיו כל עוד יש לו את package.json. כל מה שצריך לעשות זה npm install. מייד אחרי שאני מתקין את המודולים האלו, יש ליצור את ה-package.json באמצעות
npm init
הפקודה הזו שואלת אותנו כמה שאלות ואז יוצרת package.json שמכיל את כל המודולים. הנה דוגמה לאחד אמיתי מתוך תוסף wp-notice:
{ "name": "wp-notice", "version": "1.3.1", "description": "For validation and auto tests.", "main": "Gruntfile.js", "directories": { "test": "tests" }, "dependencies": { "autoprefixer": "^6.0.3", "autoprefixer-core": "^6.0.1", "grunt": "^0.4.5", "grunt-contrib-jshint": "^0.11.3", "grunt-phpcbf": "^0.1.0", "grunt-phpcs": "^0.4.0", "grunt-postcss": "^0.6.0", "jshint": "^2.8.0" }, "repository": { "type": "git", "url": "https://github.com/barzik/wp-notice.git" }, "author": "Ran Bar-Zik", "license": "ISC", "bugs": { "url": "https://github.com/barzik/wp-notice/issues" }, "homepage": "https://github.com/barzik/wp-notice", "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" } }
עכשיו, ניגש ל Gruntfile.js ונגדיר משימות עבור jshint ועבור phpcs. הרצה של grunt jshint תבצע jshint לפי הסטנדרטים לקבצי ה-JS. הרצת grunt phpcs תבצע בדיקה של סטנדרטים בכל קבצי ה-PHP בתוסף שלי.
אצור גם משימת lint שמריצה את שתי המשימות. כלומר כתיבה של grunt lint מריצה את שתיהן. כך נראה קובץ ה-Gruntfile.js שלי:
module.exports = function(grunt) { grunt.initConfig({ //object with all tasks. phpcs: { application: { src: ['./public/**/*.php' , './admin/**/*.php'] }, options: { standard: 'WordPress', errorSeverity: 1 } }, jshint: { all: ['Gruntfile.js', 'public/**/*.js', 'admin/**/*.js'], options : { curly : true, eqeqeq : true, immed : true, latedef : true, newcap : false, noarg : true, sub : true, undef : true, unused : true, boss : true, eqnull : true, browser : true, jquery : true, globals : {objectL10n : true, module : true, require : true} } } }); grunt.registerTask('lint', [ 'jshint', 'phpcs' ]); grunt.loadNpmTasks('grunt-phpcs'); grunt.loadNpmTasks('grunt-contrib-jshint'); };
בשלב הזה כדאי לוודא בסביבה המקומית ש grunt lint עובד.
עכשיו ניגש לאימפלמנטציה ב-Travis CI. מי שקרא את המאמר שלי או בחן את אחד התוספים שלי, יודע שאני נוהג להכניס את כל הפונקציות של travis CI לתוך קובץ שנקרא install-wp-tests.sh. לתוכו אני מכניס את הפונקציה שמתקינה את phpcs ואת כל המודולים שנמצאים ב-package.json:
run_phpcs() { pear config-set auto_discover 1 pear install PHP_CodeSniffer git clone git://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git $(pear config-get php_dir)/PHP/CodeSniffer/Standards/WordPress phpenv rehash npm install -g jshint phpcs --config-set installed_paths $(pear config-get php_dir)/PHP/CodeSniffer/Standards/WordPress phpcs -i local FOLDER_PATH=$(dirname $DIR) cd $FOLDER_PATH npm install grunt lint }
ואותה אני מפעיל עם:
run_phpcs
מי שרוצה דוגמה חיה יכול לראות את הבילד של wp-notice ששם רואים ממש איך הכל נבנה:
+cd /tmp/wordpress/ +run_phpcs +pear config-set auto_discover 1 +php -S 0.0.0.0:12000 router.php PHP 5.6.5 Development Server started at Mon Sep 28 16:12:00 2015 Listening on http://0.0.0.0:12000 Document root is /tmp/wordpress Press Ctrl-C to quit. config-set succeeded +pear install PHP_CodeSniffer downloading PHP_CodeSniffer-2.3.4.tgz ... Starting to download PHP_CodeSniffer-2.3.4.tgz (473,411 bytes) ................................................................................................done: 473,411 bytes install ok: channel://pear.php.net/PHP_CodeSniffer-2.3.4 ++pear config-get php_dir +git clone git://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git /home/travis/.phpenv/versions/5.6.5/pear/PHP/CodeSniffer/Standards/WordPress Cloning into '/home/travis/.phpenv/versions/5.6.5/pear/PHP/CodeSniffer/Standards/WordPress'... remote: Counting objects: 4023, done. remote: Total 4023 (delta 0), reused 0 (delta 0), pack-reused 4023 Receiving objects: 100% (4023/4023), 738.45 KiB | 0 bytes/s, done. Resolving deltas: 100% (2265/2265), done. Checking connectivity... done. +phpenv rehash +npm install -g jshint -e/travis/.nvm/v0.10.36/bin/jshint -> /home/travis/.nvm/v0.10.36/lib/node_modules/jshint/bin/jshint [email protected] /home/travis/.nvm/v0.10.36/lib/node_modules/jshint ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ([email protected]) ├── [email protected] ([email protected]) ├── [email protected] ([email protected]) ├── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected]) └── [email protected] ++pear config-get php_dir +phpcs --config-set installed_paths /home/travis/.phpenv/versions/5.6.5/pear/PHP/CodeSniffer/Standards/WordPress Config value "installed_paths" added successfully +phpcs -i The installed coding standards are MySource, PEAR, PHPCS, PSR1, PSR2, Squiz, Zend, WordPress-Core, WordPress-Docs, WordPress-Extra, WordPress-VIP and WordPress ++dirname /home/travis/build/barzik/wp-notice/tests +local FOLDER_PATH=/home/travis/build/barzik/wp-notice +cd /home/travis/build/barzik/wp-notice +npm install -npm WARN engine [email protected]: wanted: {"node":">=0.12"} (current: {"node":"0.10.36","npm":"1.4.28"}) |npm WARN engine [email protected]: wanted: {"node":">=0.12"} (current: {"node":"0.10.36","npm":"1.4.28"}) /odules/autoprefixer-core [email protected] node_modules/grunt-phpcs [email protected] node_modules/grunt-phpcbf [email protected] node_modules/grunt-contrib-jshint └── [email protected] [email protected] node_modules/grunt-postcss ├── [email protected] ├── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected]) ├── [email protected] └── [email protected] ([email protected], [email protected], [email protected]) [email protected] node_modules/grunt ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ([email protected]) ├── [email protected] ([email protected], [email protected]) ├── [email protected] ├── [email protected] ([email protected], [email protected]) ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ([email protected], [email protected]) ├── [email protected] ([email protected], [email protected]) └── [email protected] ([email protected], [email protected], [email protected]) [email protected] node_modules/jshint ├── [email protected] ├── [email protected] ([email protected]) ├── [email protected] ├── [email protected] ([email protected]) ├── [email protected] ├── [email protected] ([email protected]) ├── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected]) └── [email protected] [email protected] node_modules/autoprefixer ├── [email protected] ├── [email protected] ├── [email protected] ([email protected], [email protected], [email protected]) └── [email protected] +grunt lint >> Local Npm module "grunt-phpunit" not found. Is it installed? Running "jshint:all" (jshint) task >> 2 files lint free. Running "phpcs:application" (phpcs) task >> 9 files lint free. Done, without errors.
וזה הכל! מאוד פשוט, נעים ונחמד. כך אפשר לוודא בקלות ש-pull requests לתוסף שלכם לא רק עוברות את המבדקים האוטומטיים אלא גם עומדות לפי כל התקנים.