اختبار جافا سكريبت مع PhantomJS
() translation by (you can also view the original English article)
لا أعتقد أنني بحاجة إلى إقناعك بأن اختبار شفرة جافا سكريبت هو فكرة جيدة. ولكن ، يمكن أن يثبت في بعض الأحيان أنها مملة لاختبار شفرة جافا سكريبت التي تتطلب DOM. هذا يعني أنك بحاجة إلى اختبار شفرتك في المتصفح ولا يمكنك استخدام الجهاز ، أليس كذلك؟ خطأ ، في الواقع: أدخل PhantomJS.
:ما هو بالضبط PhantomJS؟ حسنًا ، إليك فيلم من موقع PhantomJS:
PhantomJS عبارة عن WebKit بلا واجهة باستخدام واجهة برمجة تطبيقات جافا سكريبت.
كما تعلم ، يعد Webkit هو محرك التصميم الذي يستخدمه Chrome و Safari وبضعة متصفحات أخرى. لذا PhantomJS هو متصفح ، ولكن متصفح بلا رأس. هذا يعني أن صفحات الويب المقدمة لا يتم عرضها في الواقع. قد يكون هذا الصوت غريب لك؛ حيث يمكن أن تفكر في أنها كمستعرض لبرمجة المحطة الطرفية. سنلقي نظرة على مثال بسيط في دقيقة واحدة، ولكن نحتاج أولاً لتثبيت فانتومجس.
تثبيت phantomJS
إن تثبيت PhantomJS بسيط جدًا في الحقيقة: إنه مجرد ملف ثنائي واحد تقوم بتنزيله وتثبيته في مسارك الطرفي. في صفحة تنزيل PhantomJS ، اختر نظام التشغيل الخاص بك وقم بتنزيل الحزمة الصحيحة. ثم قم بنقل الملف الثنائي من الحزمة التي تم تنزيلها إلى دليل داخل مسارك الطرفي (أحب وضع هذا النوع من الأشياء في ~ / bin).
إذا كنت تستخدم نظام التشغيل Mac OS X ، فهناك طريقة أبسط لتثبيت PhantomJS (وهي بالفعل الطريقة التي استخدمتها). مجرد استخدام البيرة ، مثل هذا:
1 |
brew update && brew install phantomjs |
يجب عليك الآن تثبيت PhantomJS. يمكنك التحقق مرة أخرى من التثبيت عن طريق تشغيل هذا:
1 |
phantomjs --version
|
أنا أرى 1.7.0؛ أنت؟
مثال صغير
دعونا نبدأ بمثال صغير.
simple.js
1 |
console.log("we can log stuff out."); |
2 |
|
3 |
function add(a, b) { |
4 |
return a + b; |
5 |
}
|
6 |
|
7 |
conslole.log("We can execute regular JS too:", add(1, 2)); |
8 |
|
9 |
phantom.exit(); |
المضي قدما وتشغيل هذه التعليمات البرمجية بواسطة إصدار الأمر التالي:
1 |
phantomjs simple.js |
.يجب أن تشاهد الإخراج من سطرين console.log
في الإطار الطرفي الخاص بك..
بالتأكيد ، هذا بسيط ، لكنه يعمل نقطة جيدة: PhantomJS يمكنه تنفيذ JavaScript تمامًا مثل المستعرض. ومع ذلك ، لا يحتوي هذا المثال على أي شفرة خاصة بـ PhantomJS ... بشكل جيد ، بخلاف السطر الأخير. هذا سطر مهم لكل نص PhantomJS لأنه يخرج من البرنامج النصي. قد لا يكون هذا منطقيًا هنا ، ولكن تذكر أن جافا سكريبت لا تنفذ دائمًا خطيًا. على سبيل المثال ، قد ترغب في وضع استدعاء exit ()
في وظيفة رد اتصال.
دعونا ننظر في مثال أكثر تعقيداً.
تحميل الصفحات
باستخدام واجهة برمجة تطبيقات PhantomJS ، يمكننا بالفعل تحميل أي عنوان URL والعمل مع الصفحة من منظورين:
- كجافا سكريبت على الصفحة.
- كمستخدم يبحث في الصفحة.
لنبدأ باختيار تحميل صفحة. قم بإنشاء ملف نصي جديد وقم بإضافة التعليمة البرمجية التالية:
script.js
1 |
var page = require('webpage').create(); |
2 |
|
3 |
page.open('http://net.tutsplus.com', function (s) { |
4 |
console.log(s); |
5 |
phantom.exit(); |
6 |
});
|
نبدأ عن طريق تحميل وحدة صفحة الويب PhantomJS
"وإنشاء كائن صفحة ويب. ثم نطلق على طريقة open
، ونمررها بعنوان URL ووظيفة رد الاتصال ؛ يوجد داخل وظيفة رد الاتصال هذه أنه يمكننا التفاعل مع الصفحة الفعلية. .في المثال أعلاه ، نقوم فقط بتسجيل حالة الطلب ، المقدمة من معلمة وظيفة رد الاتصال. إذا قمت بتشغيل هذا البرنامج النصي (مع phantomjs script.js)
، يجب أن تحصل على "نجاح" المطبوعة في المحطة.
ولكن لنجعل هذا أكثر إثارة للاهتمام عن طريق تحميل صفحة وتنفيذ بعض جافا سكريبت عليه. نبدأ بالرمز أعلاه ، ولكننا نجري مكالمة إلى page.evaluate
1 |
page.open('http://net.tutsplus.com', function () { |
2 |
var title = page.evaluate(function () { |
3 |
var posts = document.getElementsByClassName("post"); |
4 |
posts[0].style.backgroundColor = "#000000"; |
5 |
return document.title; |
6 |
});
|
7 |
page.clipRect = { top: 0, left: 0, width: 600, height: 700 }; |
8 |
page.render(title + ".png"); |
9 |
phantom.exit(); |
10 |
});
|
PhantomJS هو متصفح ، ولكن متصفح بلا رأس.
الوظيفة أننا نمرره إلى page.evaluate
. يتم تنفيذ التقييم كجافا سكريبت على صفحة الويب المحملة. في هذه الحالة ، نجد جميع العناصر مع فئة المشاركة.
بعد ذلك ، قمنا بتعيين خلفية المنشور الأول إلى اللون الأسود. أخيرًا ، نعيد document.title.
هذه ميزة رائعة ، وتعطي evaluate
من رد الاتصال الخاص بنا وتعيينها لمتغير (في هذه الحالة ، tittle
).
ثم ، نقوم بتعيين clipRect
على الصفحة ؛ هذه هي أبعاد لقطة الشاشة التي نتخذها باستخدام طريقة العرض
. كما ترى ، قمنا بتعيين القيم العليا
واليسرى
لتعيين نقطة البداية ، كما قمنا أيضًا بتعيين العرض
والارتفاع
. وأخيرًا ، نسميه page.render
، ونمرر عليه اسمًا للملف (متغير العنوان)
. ثم ، ننتهي عن طريق استدعاء phantom.exit ().
المضي قدما وتشغيل هذا البرنامج النصي ، ويجب أن يكون لديك صورة تبدو مثل هذا:almudiu qu



يمكنك مشاهدة كلا الجانبين للعملة فانتومجس هنا: يمكننا تنفيذ جافا سكريبت من داخل الصفحة، وأيضا تنفيذ من الخارج، على سبيل المثال الصفحة نفسها.
لقد كان هذا ممتعا ، ولكن ليس مفيدا كثيرا. دعونا نركز على استخدام PhantomJS عند اختبار جافا سكريبت ذات الصلة بـ DOM.
اختبار مع phantomJS
يستخدم Yeoman PhantomJS في إجراء الاختبار الخاص به ، وهو سلس تقريبا.
بالنسبة إلى الكثير من شفرة جافا سكريبت ، يمكنك الاختبار دون الحاجة إلى DOM ، ولكن هناك أوقات يحتاج فيها اختباراتك للعمل مع عناصر HTML. إذا كنت مثلي وتفضل إجراء اختبارات على سطر الأوامر ، فهذا هو المكان الذي تدخل فيه PhantomJS.
بالطبع ، ليست PhantomJS مكتبة اختبار ، ولكن يمكن تشغيل العديد من مكتبات الاختبار الشائعة الأخرى على PhantomJS. كما يمكنك أن ترى من صفحة ويكي PhantomJS على الاختبار بدون رأس ، فإن متسابقي اختبار PhantomJS متاحون إلى حد كبير لكل مكتبة اختبار قد ترغب في استخدامها. دعونا ننظر في كيفية استخدام PhantomJS مع الياسمين و Mocha.
أولا ، ياسمين وإخلاء المسؤولية: ليس هناك عداء PhantomJS جيد لياسمين في هذا الوقت. إذا كنت تستخدم Windows و Visual Studio ، يجب عليك التحقق من Chutzpah ، ويجب على مطوري Rails محاولة guard-jasmine. ولكن بخلاف ذلك ، فإن دعم Jasmine + PhantomJS قليل.
لهذا السبب ، أوصي باستخدام Mocha للاختبارات المتعلقة بـ DOM.
ومع ذلك.
من الممكن أن يكون لديك مشروع باستخدام ياسمين بالفعل وتريد استخدامه مع PhantomJS. أحد المشاريع ، وهو phantom-jasmine ، القليل من العمل لإعداده ، ولكن يجب عليه أن يفعل الحيلة.
لنبدأ بمجموعة من اختبارات JasmineJS. قم بتنزيل الرمز الخاص بهذا البرنامج التعليمي (الارتباط الموجود في الأعلى) ، وتحقق من مجلد jasmine-starter.
سترى أنه لدينا ملف tests.js
واحد يقوم بإنشاء عنصر DOM ، ويعين بعض الخصائص ، ويضيفه إلى النص الأساسي. بعد ذلك ، نجري بعض اختبارات ياسمين لتأكد من أن هذه العملية تعمل بالفعل بشكل صحيح. فيما يلي محتويات هذا الملف:
tests.js
1 |
describe("DOM Tests", function () { |
2 |
var el = document.createElement("div"); |
3 |
el.id = "myDiv"; |
4 |
el.innerHTML = "Hi there!"; |
5 |
el.style.background = "#ccc"; |
6 |
document.body.appendChild(el); |
7 |
|
8 |
var myEl = document.getElementById('myDiv'); |
9 |
it("is in the DOM", function () { |
10 |
expect(myEl).not.toBeNull(); |
11 |
});
|
12 |
|
13 |
it("is a child of the body", function () { |
14 |
expect(myEl.parentElement).toBe(document.body); |
15 |
});
|
16 |
|
17 |
it("has the right text", function () { |
18 |
expect(myEl.innerHTML).toEqual("Hi there!"); |
19 |
});
|
20 |
|
21 |
it("has the right background", function () { |
22 |
expect(myEl.style.background).toEqual("rgb(204, 204, 204)"); |
23 |
});
|
24 |
});
|
ملف SpecRunner.html
هو المخزون إلى حد ما. والفرق الوحيد هو أنني قمت بنقل علامات البرنامج النصي إلى الجسم لضمان تحميل DOM بشكل كامل قبل تشغيل الاختبارات. يمكنك فتح الملف في متصفح ورؤية أن جميع الاختبارات تمر على ما يرام.
دعونا ننقل هذا المشروع إلى PhantomJS. أولا ، استنساخ مشروع الوهمية-ياسمين
1 |
git clone git://github.com/jcarver989/phantom-jasmine.git |
هذا المشروع ليس منظمًا بقدر الإمكان ، ولكن هناك جزأين مهمين تحتاجين لهم:
- عداء PhantomJS (مما يجعل Jasmine يستخدم PhantomJS DOM).
- مراسل وحدة التحكم ياسمين (الذي يعطي إخراج وحدة التحكم).
كل من هذه الملفات الموجودة في المجلد lib
؛ نسخها إلى jasmine-starter/Jib
. نحتاج الآن إلى فتح ملف SpecRunner.html
الخاص بنا وضبط العناصر . إليك ما ينبغي أن تبدو عليه:
1 |
<script src="lib/jasmine-1.2.0/jasmine.js"></script> |
2 |
<script src="lib/jasmine-1.2.0/jasmine-html.js"></script> |
3 |
<script src="lib/console-runner.js"></script> |
4 |
<script src="tests.js"></script> |
5 |
|
6 |
<script>
|
7 |
var console_reporter = new jasmine.ConsoleReporter() |
8 |
jasmine.getEnv().addReporter(new jasmine.HtmlReporter()); |
9 |
jasmine.getEnv().addReporter(console_reporter); |
10 |
jasmine.getEnv().execute(); |
11 |
</script>
|
لاحظ أنه لدينا مراسلين اثنين لاختباراتنا: مراسل HTML ومراسل وحدة التحكم. هذا يعني أن SpecRunner.html
ويمكن تشغيل اختباراته في كل من المستعرض ووحدة التحكم. هذا سهل. لسوء الحظ ، نحتاج إلى أن يكون متغير console_reporter
هذا لأنه تم استخدامه داخل ملف CoffeeScript الذي نحن على وشك تشغيله.
لذا ، كيف نذهب نشغل هذه الاختبارات على وحدة التحكم؟ بافتراض أنك في مجلد jasmine-starter
على الجهاز ، إليك الأمر:
1 |
phantomjs lib/run\_jasmine\_test.coffee ./SpecRunner.html |
نحن نعمل على تشغيل البرنامج النصي \ _jasmine \ _test.coffee
مع PhantomJS ونمرر ملف SpecRunner.html
كمعلمة. يجب أن نرى شيئا من هذا القبيل:



وبطبيعة الحال، إذا فشل الاختبار، سوف تشاهد شيء كما يلي:



إذا كنت تخطط لاستخدام هذا في كثير من الأحيان ، قد يكون من الجيد نقل تشغيل \ _jasmine \ _test.coffee
إلى موقع آخر (مثل ~ / bin / run \ _jasmine \ _test.coffee)
وإنشاء اسم مستعار طرفي للأمر بأكمله. إليك طريقة القيام بذلك في Bash shell:
1 |
alias phantom-jasmine='phantomjs /path/to/run\_jasmine\_test.coffee' |
:مجرد رمي ذلك في ملفك .bashrc
أو .bash_profile
. الآن ، يمكنك فقط تشغيل:
1 |
phantom-jasmine SpecRunner.html |
الآن اختبارات ياسمين تعمل على ما يرام على المحطة عبر PhantomJS. يمكنك رؤية الرمز النهائي في مجلد jasmine-total
في التنزيل.
PhantomJS و Mocha
لحسن الحظ ، فإنه من الأسهل بكثير دمج Mocha و PhantomJS مع mocha-phantomjs. إنه سهل التثبيت جدًا إذا كان لديك تطبيق NPM مثبتًا (وهو ما يجب عليك):
1 |
npm install -g mocha-phantomjs |
يقوم هذا الأمر بتثبيت ملف mocha-phantomjs
الثنائي الذي سنستخدمه لتشغيل اختباراتنا.
في برنامج تعليمي سابق ، عرضت لك كيفية استخدام Mocha في الجهاز ، ولكنك ستفعل الأشياء بشكل مختلف عند استخدامها لاختبار كود DOM. كما هو الحال مع ياسمين ، سنبدأ بمراسل اختبار HTML يمكن تشغيله في المتصفح. جمال هذا هو أننا سنكون قادرين على تشغيل هذا الملف نفسه على محطة لنتائج اختبار وحدة التحكم مع PhantomJS. مثلما استطعنا مع ياسمين .
لذا ، دعنا نبني مشروعًا بسيطًا. إنشاء دليل المشروع والانتقال إليه. سنبدأ بملف package.json:
1 |
{
|
2 |
"name": "project", |
3 |
"version": "0.0.1", |
4 |
"devDependencies": { |
5 |
"mocha": "*", |
6 |
"chai" : "*" |
7 |
}
|
8 |
}
|
الموكا هو إطار الاختبار ، وسنستخدم Chai كمكتبة للتأكيد. نقوم بتثبيتها عن طريق تشغيل الآلية الوقائية الوطنية.
سنتصل باختبار ملف الاختبار / tests.js ،
وفي ما يلي اختباراته:
1 |
describe("DOM Tests", function () { |
2 |
var el = document.createElement("div"); |
3 |
el.id = "myDiv"; |
4 |
el.innerHTML = "Hi there!"; |
5 |
el.style.background = "#ccc"; |
6 |
document.body.appendChild(el); |
7 |
|
8 |
var myEl = document.getElementById('myDiv'); |
9 |
it("is in the DOM", function () { |
10 |
expect(myEl).to.not.equal(null); |
11 |
});
|
12 |
|
13 |
it("is a child of the body", function () { |
14 |
expect(myEl.parentElement).to.equal(document.body); |
15 |
});
|
16 |
|
17 |
it("has the right text", function () { |
18 |
expect(myEl.innerHTML).to.equal("Hi there!"); |
19 |
});
|
20 |
|
21 |
it("has the right background", function () { |
22 |
expect(myEl.style.background).to.equal("rgb(204, 204, 204)"); |
23 |
});
|
24 |
});
|
إنها تشبه إلى حد بعيد اختبارات الياسمين ، لكن بنية تأكيد تشاي مختلفة بعض الشيء (لذا ، لا تنسخ فقط اختبارات الياسمين الخاصة بك).
آخر قطعة من اللغز هو ملف TestRunner.html:
1 |
<html>
|
2 |
<head>
|
3 |
<title> Tests </title> |
4 |
<link rel="stylesheet" href="./node_modules/mocha/mocha.css" /> |
5 |
</head>
|
6 |
<body>
|
7 |
<div id="mocha"></div> |
8 |
<script src="./node_modules/mocha/mocha.js"></script> |
9 |
<script src="./node_modules/chai/chai.js"></script> |
10 |
<script>
|
11 |
mocha.ui('bdd'); |
12 |
mocha.reporter('html'); |
13 |
var expect = chai.expect; |
14 |
</script>
|
15 |
<script src="test/test.js"></script> |
16 |
<script>
|
17 |
if (window.mochaPhantomJS) { mochaPhantomJS.run(); } |
18 |
else { mocha.run(); } |
19 |
</script>
|
20 |
</body>
|
21 |
</html>
|
هناك عدة عوامل مهمة هنا. أولاً ، لاحظ أن هذا اكتمل للتشغيل في المستعرض ؛ لدينا CSS و JavaScript من الوحدات النمطية للعقدة التي قمنا بتثبيتها. ثم ، لاحظ علامة البرنامج النصي المضمنة. يحدد له إذا تم تحميل PhantomJS ، إذا كان الأمر كذلك ، يعمل على تشغيل وظيفة PhantomJS. خلاف ذلك ، فإنه يتمسك مع وظائف موكا الخام. يمكنك تجربة ذلك في المتصفح ومشاهدته يعمل.
لتشغيله في وحدة التحكم، ببساطة شغل هذا:
1 |
mocha-phantomjs TestRunner.html |
فويلا! أنت الآن تجري اختبارات في وحدة التحكم ، وكل ذلك بفضل PhantomJS.
PhantomJS و Yeoman
أراهن أنك لم تكن تعرف أن Yeoman الشعبي يستخدم PhantomJS في إجراء الاختبار الخاص به ، وأنه لا مبرر له. دعونا ننظر في مثال سريع. سأفترض أن لديك Yeoman اقامة.
قم بإنشاء دليل مشروع جديد ، وقم بتشغيل yeoman init
داخله ، ثم أجب بـ "لا" على جميع الخيارات. افتح ملف test / index.html
، وستجد علامة نصية بالقرب من الأسفل مع تعليق يخبرك باستبدالها بمواصفاتك الخاصة. تجاهل هذه النصيحة بشكل جيد واضع هذا
داخل كتلة:
1 |
var el = document.createElement("div"); |
2 |
expect(el.tagName).to.equal("DIV"); |
الآن ، قم بتشغيل اختبار yeoman
، وسترى أن الاختبار يعمل بشكل جيد. الآن ، افتح ملف test / index.html
في المتصفح. إنها تعمل! في احسن الاحوال!
بالطبع ، هناك الكثير الذي يمكنك القيام به مع Yeoman ، لذلك تحقق من الوثائق لمزيد من المعلومات.
الاستنتاج
استخدم المكتبات التي تمد PhantomJS لجعل اختبارك أكثر بساطة.
إذا كنت تستخدم PhantomJS بمفردها ، فلا يوجد أي سبب لتعلم عن PhantomJS نفسها ؛ يمكنك أن تعرف فقط أنها موجودة واستخدام المكتبات التي تمد PhantomJS لجعل الاختبار الخاص بك أبسط.
نأمل أن يكون شجعك هذا البرنامج التعليمي للنظر في PhantomJS. أوصي البدء بالمثال على المستندات والوثائق التي تقدمها PhantomJS ؛ سوف يفتحون عينيك فعلاً على ما يمكنك فعله باستخدام PhantomJS - كل شيء بدءًا من أتمتة الصفحة إلى شبكة الاستنشاق. الرابط 1 الرابط 2
لذا ، هل يمكنك التفكير في مشروع من شأنه تحسين PhantomJS؟ دعونا نسمع عن ذلك في التعليقات!