الرغبة في الابتعاد عن اختبار الانحدار اليدوي سبب وجيه لتقديم الاختبارات الذاتية. والسؤال هو أي منها؟ استذكر مطورو الواجهة ناتاليا ستوس وأليكسي أندروسوف كيف مر فريقهما بالعديد من التكرارات وبنوا اختبار الواجهة الأمامية في Auto.ru بناءً على Jest و Puppeteer: اختبارات الوحدة ، اختبارات مكونات React الفردية ، اختبارات التكامل. الأكثر إثارة للاهتمام من هذه التجربة هو الاختبار المعزول لمكونات React في مستعرض بدون شبكة Silenium Grid و Java وأشياء أخرى.

أليكس:
- أولاً ، عليك أن تخبر قليلاً عن أخبار السيارات. هذا هو موقع بيع السيارات. هناك بحث وحساب شخصي وخدمات سيارات وقطع غيار ومراجعات ووكلاء وغير ذلك الكثير. Auto.ru هو مشروع كبير جدا ، والكثير من التعليمات البرمجية. نكتب كل الكود في شكل مونوريب كبير ، لأنه مختلط. نفس الأشخاص يقومون بمهام مماثلة ، على سبيل المثال ، للجوال وسطح المكتب. لقد ظهر الكثير من الكود ، و monorepa أمر حيوي بالنسبة لنا. والسؤال هو كيفية اختباره؟

لدينا React و Node.js ، التي تقوم بإجراء التقديم من جانب الخادم وتطلب البيانات من الواجهة الخلفية. القطع المتبقية والصغيرة على BEM.

ناتاليا:
- بدأنا التفكير نحو الأتمتة. وشملت دورة الافراج عن التطبيقات الفردية لدينا عدة خطوات. أولاً ، تم تطوير الميزة بواسطة مبرمج في فرع منفصل. بعد ذلك ، في نفس الفرع المنفصل ، يتم اختبار الميزة بواسطة اختبار يدوي. إذا كان كل شيء على ما يرام ، فإن المهمة تقع في مرشح الإفراج. إذا لم يكن كذلك ، فارجع إلى تكرار التطوير مرة أخرى ، واختبر مرة أخرى. حتى يخبر المختبر أن كل شيء على ما يرام في هذه الميزة ، فلن يقع في مرشح الإصدار.
بعد تجميع مرشح الإصدار ، يوجد انحدار يدوي - ليس فقط Auto.ru ، ولكن فقط الحزمة التي سنقوم بلفها. على سبيل المثال ، إذا كنا سنقوم بنقل شبكة سطح المكتب ، فهناك تراجع يدوي لشبكة سطح المكتب. هذه هي الكثير من حالات الاختبار اليدوي. استغرق هذا الانحدار حوالي يوم عمل واحد من اختبار يدوي.
عند اكتمال الانحدار ، يحدث إصدار. بعد ذلك ، فرع التحرير يدمج في السيد. في هذه المرحلة ، يمكننا فقط حقن الكود الرئيسي ، الذي قمنا باختباره فقط على الويب لسطح المكتب ، ويمكن لهذا الكود كسر الويب النقال ، على سبيل المثال. لم يتم التحقق من ذلك على الفور ، ولكن فقط في الانحدار اليدوي التالي - الويب للجوال.

بطبيعة الحال ، كان المكان الأكثر إيلامًا في هذه العملية هو الانحدار اليدوي ، والذي استغرق وقتًا طويلاً للغاية. بطبيعة الحال ، تعبت جميع الفاحصات اليدوية من فعل الشيء نفسه كل يوم. لذلك ، قررنا أتمتة كل شيء. الحل الأول الذي تم تنفيذه هو اختبارات سيلينيوم وجافا الذاتية ، التي كتبها فريق منفصل. كانت هذه اختبارات شاملة ، e2e ، والتي اختبرت التطبيق بأكمله. لقد كتبوا حوالي 5 آلاف من هذه الاختبارات. ماذا انتهى بنا المطاف؟
وبطبيعة الحال ، قمنا بتسريع الانحدار. تمر الاختبارات التلقائية بشكل أسرع بكثير مما يحدث في الاختبار اليدوي ، حيث يتم تشغيله بمعدل 10 مرات تقريبًا. وفقًا لذلك ، تمت إزالة الإجراءات الروتينية التي قاموا بها يوميًا من الفاحصات اليدوية. الأخطاء التي تم العثور عليها من الاختبارات الذاتية أسهل في التكاثر. ما عليك سوى إعادة تشغيل هذا الاختبار أو إلقاء نظرة على الخطوات التي يقوم بها - على عكس جهاز الاختبار اليدوي الذي سيقول: "لقد قمت بالنقر فوق شيء ما وكسر كل شيء".
توفير الاستقرار للطلاء. نحن دائمًا نجري اختبارات التشغيل نفسها - على النقيض من ذلك ، مرة أخرى ، من الاختبار اليدوي ، عندما يمكن للمفحص أن يفكر في أننا لم نلمس هذا المكان ، ولن أتحقق منه هذه المرة. لقد أضفنا اختبارات لمقارنة لقطات الشاشة ، وحسّننا دقة اختبار واجهة المستخدم - الآن نتحقق من التناقض في بضع بكسلات لن يراها المختبر مع عينيه. كل الشكر لاختبارات لقطة الشاشة.
ولكن كان هناك سلبيات. الأكبر - بالنسبة لاختبارات e2e ، نحتاج إلى بيئة اختبار متوافقة تمامًا مع المنتج. يجب دائمًا تحديثه وتشغيله. هذا يتطلب قوة تقريبا مثل بيع دعم الاستقرار. بطبيعة الحال ، لا يمكننا دائما تحمله. لذلك ، غالبًا ما واجهنا مواقف تكذب فيها بيئة الاختبار أو في مكان ما تم فيه كسر شيء ما ، وفشلت الاختبارات ، على الرغم من عدم وجود مشكلات في الحزمة الأولى.
يتم تطوير هذه الاختبارات أيضًا بواسطة فريق منفصل ، له مهامه الخاصة ، بدوره الخاص به في تعقب المهام ، ويتم تغطية الميزات الجديدة ببعض التأخير. لا يمكن أن تأتي مباشرة بعد إصدار ميزة جديدة والكتابة على الفور autotests. نظرًا لأن الاختبارات باهظة الثمن ويصعب كتابتها وصيانتها ، فإننا لا نغطي جميع السيناريوهات معهم ، ولكن فقط السيناريوهات الأكثر أهمية. في الوقت نفسه ، هناك حاجة إلى فريق منفصل ، وسيكون لديه أدوات منفصلة ، بنية تحتية منفصلة ، كل ما يخصه. وتحليل الاختبارات المتساقطة هو أيضًا مهمة غير تافهة للمختبرين اليدويين أو للمطورين. سأعرض بعض الأمثلة.

لدينا اختبارات المدى. 500 الاختبارات مرت ، والتي سقط بعضها. يمكننا أن نرى مثل هذا الشيء في التقرير. هنا لم يبدأ الاختبار ببساطة ، وليس من الواضح ما إذا كان كل شيء جيدًا أم لا.

مثال آخر - بدأ الاختبار ، لكنه تعطل بسبب هذا الخطأ. لم يتمكن من العثور على أي عنصر في الصفحة ، لكن لماذا - لا نعرف. إما أن هذا العنصر لم يظهر ببساطة ، أو اتضح أنه موجود على الصفحة الخطأ ، أو تغير محدد الموقع. كل ما تحتاجه للذهاب والأيدي debazh.

اختبارات لقطة الشاشة لا تمنحنا دائمًا دقة جيدة. هنا نقوم بتحميل بعض البطاقات ، لقد تحركت قليلاً ، وانخفض اختبارنا.

حاولنا حل عدد من هذه المشاكل. بدأنا في تشغيل جزء من الاختبارات على المنتج - الاختبارات التي لا تؤثر على بيانات المستخدم لا تغير أي شيء في قاعدة البيانات. وهذا هو ، لقد صنعنا في prod آلة منفصلة تبحث في بيئة prod. نحن فقط نثبت حزمة الواجهة الأمامية الجديدة ونجري الاختبارات هناك. المنتج مستقر على الأقل.
لقد قمنا بنقل بعض الاختبارات إلى mokeys ، لكن لدينا الكثير من الواجهات الخلفية المختلفة ، واجهات برمجة التطبيقات المختلفة ، وحبسها كلها مهمة صعبة للغاية ، لا سيما بالنسبة لـ 5000 اختبار. لهذا الغرض ، تمت كتابة خدمة خاصة تسمى mockritsa ، وهي تساعد على جعل الموكاتا اللازمة للواجهة الأمامية بسهولة ويسيرة إلى حد ما.
لقد اضطررنا أيضًا إلى شراء مجموعة كبيرة من الحديد بحيث تكون شبكة السيلينيوم الخاصة بنا التي يتم إطلاق هذه الاختبارات عليها أكبر بحيث لا تسقط ، لأنها لا تستطيع رفع المستعرض ، وبالتالي ، ستعمل بشكل أسرع. حتى بعد أن حاولنا حل هذه المشكلات ، ما زلنا توصلنا إلى استنتاج مفاده أن مثل هذه الاختبارات ليست مناسبة لـ CI ، فهي تستغرق وقتًا طويلاً للغاية. لا يمكننا تشغيلها على كل طلب تجمع. نحن ببساطة لن نقوم أبدًا في حياتنا بتحليل هذه التقارير لاحقًا ، والتي سيتم إنشاؤها لكل طلب تجميع.

وفقًا لذلك ، بالنسبة إلى CI ، نحتاج إلى اختبارات سريعة ومستقرة لن تفشل لبعض الأسباب العشوائية. نريد تشغيل اختبارات لطلب البلياردو دون أي منصات اختبار أو خلفية أو قواعد بيانات دون أي حالات مستخدم معقدة.
نريد أن تتم كتابة هذه الاختبارات في نفس الوقت مع الرمز ، وأن توضح نتائج الاختبارات على الفور أي ملف حدث خطأ.
أليكس:
- نعم ، وقررنا تجربة كل ما نريد ، لتصويب كل شيء من البداية إلى النهاية في نفس بنية Jest الأساسية. لماذا اخترنا Jest؟ لقد كتبنا بالفعل اختبارات وحدة على Jest ، لقد أحببنا ذلك. هذه أداة شائعة مدعومة ، لديها بالفعل مجموعة من عمليات الدمج الجاهزة هناك: React test test ، Enzyme. كل شيء يعمل خارج الصندوق ، لا شيء يحتاج إلى بناء ، كل شيء بسيط.

وفاز Jest شخصيًا بالنسبة لي ، على عكس أي موكا ، من الصعب تصوير التأثير الجانبي لنوع من اختبار الطرف الثالث في ساقك إذا نسيت تنظيفه أو أي شيء آخر. في موكا ، يتم ذلك مرة أو مرتين ، ولكن في Jest يصعب القيام بذلك: يتم إطلاقه باستمرار في خيوط منفصلة. إنه ممكن ، لكنه صعب. و e2e صدر Puppeteer ، قررنا أيضا أن نحاول ذلك. هذا ما حصلنا عليه.

ناتاليا:
"سأبدأ أيضًا بمثال عن اختبارات الوحدة". عندما نكتب اختبارات ببساطة لبعض الوظائف ، لا توجد مشاكل خاصة. نحن نسمي هذه الوظيفة ، ونمرر بعض الحجج ، ونقارن ما حدث بما كان يجب أن يحدث.
إذا كنا نتحدث عن مكونات React ، فسيصبح كل شيء أكثر تعقيدًا. نحن بحاجة إلى تقديمها بطريقة أو بأخرى. يوجد عارض اختبار React ، ولكنه ليس مناسبًا جدًا لاختبارات الوحدات ، لأنه لن يسمح لنا باختبار المكونات بمعزل عن غيرها. وسوف تجعل المكون تماما حتى النهاية ، إلى التصميم.
وأريد أن أوضح كيف من خلال الإنزيم ، من الممكن كتابة اختبارات وحدة لمكونات React باستخدام مثال على هذا المكون حيث لدينا مكون معين من MyComponent. يحصل على نوع من الدعم ، لديه نوع من المنطق. ثم يعيد مكون Foo ، والذي بدوره سيعود مكون الشريط ، والذي يعود بالفعل إلى مكون الشريط ، في الواقع ، التصميم.

يمكننا استخدام أداة إنزيم مثل التقديم الضحل. هذا ما نحتاجه فقط لاختبار مكون MyComponent بمعزل عن غيره. ولن تعتمد هذه الاختبارات على المكونات التي سيحتويها الشريط والشريط داخل أنفسهم. سنقوم فقط باختبار منطق المكون MyComponent.
Jest لديه شيء مثل Snapshot ، ويمكنهم أيضًا مساعدتنا هنا. "توقع شيء toMatchSnapshot" سيخلق مثل هذا الهيكل بالنسبة لنا ، فقط ملف نصي يخزن ، في الواقع ، ما مررنا بتوقعه ، ما يحدث ، وعندما يتم تشغيل هذه الاختبارات لأول مرة ، تتم كتابة هذا الملف. مع إجراء مزيد من الاختبارات ، سيتم مقارنة ما تم الحصول عليه بالمعيار الموجود في الملف MyComponent.test.js.snap.
هنا نرى أن العرض بالكامل ، يُرجع بالضبط ما تُظهره طريقة التجسيد من MyComponent ، وما هو foo ، بشكل عام ، لا يهم. يمكننا كتابة مثل هذين الاختبارين لحالتنا ، ولحالتين لمكون MyComponent.

من حيث المبدأ ، يمكننا اختبار نفس الشيء دون لقطة ، فقط التحقق من البرامج النصية التي نحتاجها ، على سبيل المثال ، التحقق من الدعامة التي يتم تمريرها إلى المكون فو. ولكن هذا النهج لديه واحد ناقص. إذا أضفنا بعض العناصر الأخرى إلى MyComponent ، اختبارنا الجديد ، فلن يتم عرض ذلك بأي شكل من الأشكال.

لذلك ، بعد كل شيء ، اختبارات اللقطات هي تلك التي ستظهر لنا أي تغييرات تقريبًا داخل المكون. ولكن إذا كتبنا كلا الاختبارين على لقطة ، ثم أجرينا نفس التغييرات في المكون ، فسنرى أن كلا الاختبارين سوف يسقط. من حيث المبدأ ، ستخبرنا نتائج هذه الاختبارات الساقطة عن نفس الشيء ، حيث أضفنا نوعًا من "الترحيب" هناك.

وهذا ضروري أيضًا ، لذلك ، أعتقد أنه من الأفضل استخدام اختبار لقطة واحدة لنفس الهيكل. تحقق من بقية المنطق بطريقة مختلفة ، بدون لقطة ، لأن هذه اللقطة ليست مؤشّرة للغاية. عندما ترى لقطة ، ترى فقط أنه تم تقديم شيء ما ، ولكن ليس من الواضح المنطق الذي اختبرته هنا. هذا غير مناسب تمامًا لـ TDD إذا كنت تريد استخدامه. ولن تعمل مثل الوثائق. هذا هو ، إذن ، عندما تذهب إلى النظر إلى هذا المكون ، سترى أن "نعم" ، يتوافق "اللقطة" مع شيء ما ، ولكن نوع المنطق الذي كان هناك غير واضح للغاية.


بنفس الطريقة ، سنكتب اختبارات الوحدة على مكون foo ، على مكون الشريط ، على سبيل المثال ، لقطة.

نحصل على تغطية 100 ٪ لهذه المكونات الثلاثة. نعتقد أننا فحصنا كل شيء ، لقد أنجزنا جيدًا.
ولكن لنفترض أننا غيرنا شيئًا ما في مكون الشريط ، وأضفنا بعضًا دعامة جديدة إليه ، وكان لدينا اختبار للعنصر الشريطي بوضوح. لقد صححنا الاختبار ، وكل الاختبارات الثلاثة تمر معنا.

لكن في الواقع ، إذا جمعنا هذه القصة بأكملها ، فلن ينجح شيء ، لأن MyComponent لن تترافق مع مثل هذا الخطأ. نحن لا نمر في الواقع الدعامة التي تتوقعها لمكون الشريط. لذلك ، نحن نتحدث عن حقيقة أننا في هذه الحالة نحتاج أيضًا إلى اختبارات تكامل ستتحقق منها ، بما في ذلك ما إذا كنا نسمي المكون الفرعي التابع له بشكل صحيح من المكون الخاص بنا.

بوجود هذه المكونات وتغيير أحدها ، سترى فورًا التغييرات التي تطرأ على هذا المكون.
ما هي الفرص التي لدينا في الإنزيم لإجراء اختبار التكامل؟ تقديم الضحلة نفسها إرجاع مثل هذا الهيكل. يحتوي على طريقة غوص فيه ، إذا تم استدعاؤه على بعض مكونات React ، فسوف يفشل فيه. وفقًا لذلك ، عند تسميته بمكون foo ، نحصل على ما يقدمه مكون foo ، فهذا شريط ، إذا فعلنا الغوص مرة أخرى ، فسوف نحصل ، في الواقع ، على التنسيق الذي سيعود إليه مكون الشريط. هذا سيكون مجرد اختبار التكامل.

أو يمكنك تقديم كل شيء مرة واحدة باستخدام طريقة التحميل ، والتي تنفذ تقديم DOM الكامل. لكنني لا أنصح بذلك ، لأنها ستكون لقطة صعبة للغاية. وكقاعدة عامة ، لا تحتاج إلى التحقق من الهيكل بالكامل. تحتاج فقط إلى التحقق من التكامل بين العنصر الأصل والمكون الفرعي في كل حالة.

وبالنسبة إلى MyComponent ، فإننا نضيف اختبار تكامل ، لذلك في الاختبار الأول أضيف الغوص فقط ، واتضح أننا اختبرنا ليس فقط منطق المكون نفسه ، ولكن أيضًا تكامله مع المكون foo. نفس الشيء ، نضيف اختبار التكامل للمكون foo الذي يسميه المكون الشريطي بشكل صحيح ، ومن ثم نتحقق من هذه السلسلة بأكملها ، ونحن على يقين من أنه لن تؤدي أي تغييرات إلى كسرنا ، في الواقع ، فإن تقديم MyComponent

مثال آخر ، بالفعل من مشروع حقيقي. فقط لفترة وجيزة حول ما يمكن أن يفعله Jest and Enzyme. يمكن أن تفعل المزاح موكي. يمكنك ، إذا كنت تستخدم بعض الوظائف الخارجية في المكون الخاص بك ، يمكنك قفله. على سبيل المثال ، في هذا المثال ، نسمي نوعًا من api ، بطبيعة الحال لا نريد الدخول في أي api في اختبار الوحدة ، لذلك نحن فقط نحذف وظيفة getResource مع بعض كائنات jest.fn. في الواقع ، وظيفة وهمية. ثم يمكننا التحقق مما إذا كان قد تم استدعاؤه أم لا ، وعدد المرات التي تم استدعاؤها ، وما هي الحجج. كل هذا يسمح لك أن تفعل Jest.

في التقديم الضحل ، يمكنك نقل المتجر إلى أحد المكونات. إذا كنت بحاجة إلى متجر ، يمكنك فقط نقله إلى هناك ، وسيعمل بنجاح.

يمكنك أيضًا تغيير الحالة والدفع في مكون مقدم بالفعل.

يمكنك استدعاء طريقة المحاكاة على بعض المكونات. انها فقط تدعو المعالج. على سبيل المثال ، إذا قمت بمحاكاة النقر ، فسوف يتصل onClick لمكون الزر هنا. كل هذا يمكن قراءته ، بالطبع ، في الوثائق الخاصة بالإنزيم ، الكثير من القطع المفيدة. هذه مجرد أمثلة قليلة من مشروع حقيقي.

أليكس:
- نأتي إلى السؤال الأكثر إثارة للاهتمام. يمكننا اختبار Jest ، يمكننا كتابة اختبارات الوحدة ، والتحقق من المكونات ، والتحقق من العناصر التي تستجيب بشكل غير صحيح للنقرة. نحن قادرون على التحقق من هتمل. الآن نحن بحاجة إلى التحقق من تخطيط المكون ، المغلق.

ومن المستحسن القيام بذلك حتى لا يختلف مبدأ الاختبار بأي شكل من الأشكال عن الذي وصفته سابقًا. إذا كنت أتحقق من html ، فعندئذٍ اتصلت بالعرض التقديمي الضحل ، فقد استلزم الأمر وجعله html لي. أريد أن أتحقق من المغلق ، ما عليك سوى الاتصال بنوع من التقديم والتأكد فقط - دون رفع أي شيء ، دون إعداد أي أدوات.

بدأت أبحث عن الأمر ، وفي كل مكان تقريبًا ، تم إعطاء نفس الإجابة على كل شيء يسمى Puppeteer ، أو شبكة السيلينيوم. تفتح بعض علامات التبويب ، وتذهب إلى صفحة html ، وتلتقط لقطة للشاشة ومقارنتها بالخيار السابق. إذا لم يتغير ، فكل شيء على ما يرام.
السؤال هو ، ما هي صفحة html إذا أردت فقط التحقق من مكون واحد بمعزل؟ من المستحسن - في ظروف مختلفة.

لا أريد أن أكتب مجموعة من هذه الصفحة أتش تي أم أل لكل مكون ، لكل ولاية. أفيتو لديه شوط جيد. نشر روما دفورنوف مقالاً عن حبري ، وألقى كلمة بالمناسبة. ماذا فعلوا؟ يأخذون المكونات ، وتجميع HTML من خلال تقديم قياسي. ثم بمساعدة الإضافات وجميع أنواع الحيل التي يجمعونها جميع الأصول التي لديهم - الصور ، المغلق. أدخل الكل في html ، وسيحصلون فقط على html الصحيح.

ثم قاموا برفع خادم خاص ، وإرسال html إلى هناك ، وتقديمه ، وإرجاع بعض النتائج. مع ذلك ، هناك مقالة مثيرة للاهتمام ، يمكنك أن تستخلص منها الكثير من الأفكار المثيرة للاهتمام.

ما لا يعجبني هناك يختلف تجميع المكون عن كيفية انتقاله إلى الإنتاج. على سبيل المثال ، لدينا webpack ، وهناك سيتم جمعها بواسطة نوع من أصول بابل ، يتم سحبها بشكل مختلف هناك. لا أستطيع أن أضمن أنني اختبرت ما سأقوم بتنزيله الآن.
ومرة أخرى ، خدمة منفصلة لقطات. أريد أن أفعل ذلك أسهل بطريقة أو بأخرى. وفي الواقع ، كانت هناك فكرة أنه ، دعونا نجمعها بالضبط كما سنجمعها. وحاول استخدام شيء مثل Docker ، لأنه شيء من هذا القبيل ، يمكن وضعه على جهاز كمبيوتر ، محليًا ، سيكون بسيطًا ومعزولًا ، ولا يمس أي شيء ، كل شيء على ما يرام.

ولكن هذه المشكلة تكمن في صفحة html ، فهي تظل كما هي بالفعل. ولدت فكرة. لديك webpack.conf مبسطة ، ومنه يوجد بعض EntryPoint للعميل js. يتم وصف الوحدات ، وكيفية تجميعها ، وملف الإخراج ، وجميع المكونات الإضافية التي وصفتها ، وتم تكوين كل شيء ، وكل شيء على ما يرام.

ماذا لو فعلت مثل هذا؟ سوف يذهب إلى مكون بلدي وجمعها في عزلة. وسيكون هناك عنصر واحد بالضبط. إذا أضفت html webpack إلى هناك ، فسوف يعطيني أيضًا html ، وسيتم جمع هذه الأصول هناك ، ومع ذلك ، يمكن بالفعل اختبار هذا الشيء تلقائيًا.
وكنت على وشك أن أكتب كل هذا ، ولكن بعد ذلك وجدت هذا.

Jest-puppeteer-React ، البرنامج المساعد الشاب. وبدأت المساهمة بنشاط في ذلك. إذا أردت فجأة تجربتها ، فيمكنك ، على سبيل المثال ، المجيء إلي ، يمكنني المساعدة بطريقة أو بأخرى. المشروع ، في الواقع ، ليس لي.
تكتب ملفًا عاديًا على أنه test.js ، وتحتاج إلى كتابة هذه الملفات بشكل منفصل للمساعدة في العثور عليها ، حتى لا يتم تجميع المشروع بالكامل نيابةً عنك ، ولكن فقط تجميع المكونات الضرورية. في الواقع ، تأخذ التكوين webpack. تتغير نقاط الإدخال إلى ملفات browser.js ، أي بالضبط ما نريد اختباره سيتم تعبئته بلغة html ، وبمساعدة Puppeteer ، ستأخذك لقطات شاشة.

ماذا يمكن أن يفعل؟ , jest-image-snapshot. . , , js, media-query, , .
headless-, , , , , headless-, Chrome . web-, , , , .
Docker. . . , Docker, . . Docker , , , Linux, - , - . Docker , .

? , . , . before-after, , . , . , Chrome, Firefox. .
. pixelmatch. , looksame, «», . , .

— . , , . , : - , — Enzyme. Redux store . . viewport, , . , , .

. , . ? , .

: 5-10 . Selenium . , , , . .

Puppeteer, e2e-. , e2e- — , Selenium.
:
— , Selenium Java , . - JS Puppeteer, , .
, . , , .

— Selenium Java, — JS Puppeteer. . 18 . , , Java. , , Java Selenium.

:
— ? . , html-, css . e2e. . , .

, , . . , , — , . , . - , , : , .
, , . git hook, -, . green master — , , , . شكرا لك