মোচা এবং নোড.জেএস সহ ব্যক্তিগত ফাংশনগুলির ইউনিট টেস্টিং


131

নোড.জেএস এর জন্য লিখিত একটি অ্যাপ্লিকেশনটি ইউনিট পরীক্ষার জন্য আমি মোচা ব্যবহার করছি

আমি অবাক হয়েছি যদি কোনও মডিউলে রফতানি না করা পরীক্ষার ফাংশনগুলি একক করা সম্ভব হয় তবে?

উদাহরণ:

আমি এই মত সংজ্ঞায়িত অনেক ফাংশন আছে foobar.js

function private_foobar1(){
    ...
}

function private_foobar2(){
    ...
}

এবং কয়েকটি ফাংশন জনসাধারণ হিসাবে রফতানি করা হয়েছে:

exports.public_foobar3 = function(){
    ...
}

পরীক্ষার কেসটি নিম্নরূপে কাঠামোযুক্ত:

describe("private_foobar1", function() {
    it("should do stuff", function(done) {
        var stuff = foobar.private_foobar1(filter);
        should(stuff).be.ok;
        should(stuff).....

স্পষ্টতই এটি কার্যকর হয় না, যেহেতু private_foobar1 রফতানি হয় না।

ইউনিট-পরীক্ষা ব্যক্তিগত পদ্ধতিগুলির সঠিক উপায় কী? মোচা কি এটির জন্য কিছু বিল্ট-ইন পদ্ধতি আছে?


সম্পর্কিত: stackoverflow.com/questions/14874208
dskrvk

উত্তর:


64

যদি ফাংশনটি মডিউল দ্বারা রফতানি না করা হয় তবে এটি মডিউলটির বাইরে টেস্ট কোড দ্বারা কল করা যায় না। এটি জাভাস্ক্রিপ্ট কীভাবে কাজ করে তার কারণে এবং মোচা নিজেই এটিকে আটকায় না।

কয়েকটি স্থানে যেখানে আমি নির্ধারণ করেছি যে একটি ব্যক্তিগত ফাংশন পরীক্ষা করা সঠিক জিনিস, আমি যা করেছি তা কিছু পরিবেশ পরিবর্তনশীল সেট করেছে যা আমার মডিউলটি পরীক্ষা সেটআপে চলছে কিনা তা নির্ধারণের জন্য যাচাই করে। যদি এটি টেস্ট সেটআপে চলে, তবে এটি অতিরিক্ত ফাংশন রফতানি করে যা আমি পরীক্ষার সময় কল করতে পারি।

"পরিবেশ" শব্দটি এখানে আলগাভাবে ব্যবহৃত হয়। এর অর্থ চেক process.envবা অন্য কিছু হতে পারে যা মডিউলে "আপনার এখন পরীক্ষা করা হচ্ছে" তে যোগাযোগ করতে পারে। যে কাজগুলিতে আমাকে এটি করতে হয়েছিল সেগুলি প্রয়োজনীয় জেএস পরিবেশে ছিল এবং আমি module.configএই উদ্দেশ্যে ব্যবহার করেছি ।


2
শর্তাধীন রফতানি মানগুলি ES6 মডিউলগুলির সাথে সামঞ্জস্যপূর্ণ বলে মনে হয় না। আমি পাচ্ছিSyntaxError: 'import' and 'export' may only appear at the top level
এআইজে

1
@aij হ্যাঁ ES6 স্ট্যাটিক রপ্তানির কারণে আপনি ব্যবহার করতে পারবেন না import, exportএকটি ব্লক ভেতরে। শেষ পর্যন্ত আপনি ES6 এ সিস্টেম লোডার দিয়ে এই ধরণের জিনিসটি সম্পাদন করতে সক্ষম হবেন। এখনই এটির কাছাকাছি যাওয়ার এক উপায় হ'ল module.exports = process.env.NODE_ENV === 'production' ? require('prod.js') : require('dev.js')আপনার এস those কোডের পার্থক্যগুলি সেই সম্পর্কিত ফাইলগুলিতে ব্যবহার এবং সঞ্চয় করা।
চেম্বারলাইন

2
আমি অনুমান করি যে আপনার যদি পুরো কভারেজ থাকে তবে আপনি আপনার সমস্ত ব্যক্তিগত ফাংশন পরীক্ষা করে দেখছেন, আপনি সেগুলি প্রকাশ করেছেন কি না।
জিগি

1
@aij আপনি শর্তসাপেক্ষে রপ্তানি করতে পারেন ... আমরা দেখি উত্তর: stackoverflow.com/questions/39583958/...
RayLoveless

187

পরীক্ষা করে দেখুন বৈদ্যুতিক তার লাগানো মডিউল। এটি আপনাকে মডিউলের মধ্যে ব্যক্তিগত ভেরিয়েবল এবং ফাংশনগুলি পেতে (এবং ম্যানিপুলেট করতে) অনুমতি দেয়।

সুতরাং আপনার ক্ষেত্রে ব্যবহারটি এমন কিছু হবে:

var rewire = require('rewire'),
    foobar = rewire('./foobar'); // Bring your module in with rewire

describe("private_foobar1", function() {

    // Use the special '__get__' accessor to get your private function.
    var private_foobar1 = foobar.__get__('private_foobar1');

    it("should do stuff", function(done) {
        var stuff = private_foobar1(filter);
        should(stuff).be.ok;
        should(stuff).....

3
@ জারো আমার কোডের বেশিরভাগই হয় এএমডি মডিউলগুলির আকারে, যা রিওয়ায়ার হ্যান্ডেল করতে অক্ষম (কারণ এএমডি মডিউলগুলি ফাংশন তবে রিওয়ায়ার "ফাংশনগুলির মধ্যে পরিবর্তনশীল" পরিচালনা করতে পারে না)। বা স্থানান্তরিত হয়, পুনর্নির্মাণের অন্য একটি দৃশ্য পরিচালনা করতে পারে না। প্রকৃতপক্ষে, যে সমস্ত লোকেরা রিভাইয়ারটি দেখতে যাচ্ছেন তারা ব্যবহার করার চেষ্টা করার আগে প্রথমে সীমাবদ্ধতাগুলি (আগে যুক্ত লিঙ্কযুক্ত) পড়া ভাল করবে। আমার একক অ্যাপ্লিকেশন নেই যা ক) "ব্যক্তিগত" সামগ্রী রফতানির প্রয়োজন এবং খ) পুনর্বার সীমাবদ্ধতার মধ্যে চলে না।
লুই

1
কেবলমাত্র একটি ছোট বিষয়, কোড কভারেজ এই জাতীয় লিখিত পরীক্ষাগুলি তুলতে ব্যর্থ হতে পারে। জাস্টের অন্তর্নির্মিত কভারেজ সরঞ্জামটি ব্যবহার করে দেখেছি কমপক্ষে।
মাইক স্টেড

রিওয়াইয়ার জাস্টের অটো-বিদ্রূপকারী সরঞ্জামের সাথে ভাল খেলছে না। আমি এখনও বিদ্রূপের সুবিধাগুলি উপার্জন এবং কিছু ব্যক্তিগত ভারতে প্রবেশ করার উপায় খুঁজছি way
বিটিবার্টন 42

সুতরাং আমি এই কাজটি করার চেষ্টা করেছি তবে আমি টাইপ স্ক্রিপ্ট ব্যবহার করছি, যা আমি অনুমান করছি যে এই সমস্যাটি সৃষ্টি করছে। মূলত আমি নিম্নলিখিত ত্রুটির পাবেন: Cannot find module '../../package' from 'node.js'। এর সাথে পরিচিত কেউ?
ক্লু

বৈদ্যুতিক তার লাগানো মধ্যে সূক্ষ্ম কাজ করা হয় .ts, typescriptআমি ব্যবহার করে চালানো ts-node @clu
muthukumar selvaraj

24

ফিলিপ ওয়ালটন, যার ব্লগের গুগল ইঞ্জিনিয়ার দ্বারা ব্যাখ্যা করা আপনার ব্যক্তিগত পদ্ধতিগুলি পরীক্ষা করার জন্য এখানে একটি দুর্দান্ত ওয়ার্কফ্লো রয়েছে

নীতি

  • আপনার কোডটি সাধারণত লিখুন
  • আপনার ব্যক্তিগত পদ্ধতিগুলি পৃথক কোড ব্লকে অবজেক্টের সাথে আবদ্ধ করুন, _উদাহরণ হিসাবে এটির দ্বারা চিহ্নিত করুন
  • শুরু এবং শেষের মন্তব্যে সেই ব্লকটিকে ঘিরে

তারপরে প্রোডাকশন বিল্ডগুলির জন্য এই ব্লকটি ফালা করতে কোনও বিল্ড টাস্ক বা আপনার নিজস্ব বিল্ড সিস্টেম (উদাহরণস্বরূপ গ্রান্ট-স্ট্রিপ-কোডের জন্য) ব্যবহার করুন।

আপনার পরীক্ষাগুলি বিল্ডগুলিতে আপনার ব্যক্তিগত এপিআইতে অ্যাক্সেস রয়েছে এবং আপনার উত্পাদন বিল্ডগুলি নেই not

টুকিটাকি

আপনার কোডটি এই হিসাবে লিখুন:

var myModule = (function() {

  function foo() {
    // private function `foo` inside closure
    return "foo"
  }

  var api = {
    bar: function() {
      // public function `bar` returned from closure
      return "bar"
    }
  }

  /* test-code */
  api._foo = foo
  /* end-test-code */

  return api
}())

এবং আপনার মত গুরুতর কাজ

grunt.registerTask("test", [
  "concat",
  "jshint",
  "jasmine"
])
grunt.registerTask("deploy", [
  "concat",
  "strip-code",
  "jshint",
  "uglify"
])

আরও গভীর

পরবর্তী নিবন্ধে , এটি "ব্যক্তিগত পদ্ধতি পরীক্ষা করার" "কেন" ব্যাখ্যা করে


1
এছাড়াও এমন একটি ওয়েবকিট প্লাগইন পাওয়া গেছে যা দেখে মনে হচ্ছে এটি একই ধরণের ওয়ার্কফ্লো সমর্থন করতে পারে: ওয়েবপ্যাক-স্ট্রিপ-ব্লক
জেআরুল

21

আপনি যদি এটি সহজ রাখতে পছন্দ করেন তবে কেবল প্রাইভেট সদস্যদেরও রফতানি করুন তবে কিছু কনভেনশনের সাথে পাবলিক এপিআই থেকে স্পষ্টভাবে পৃথক করে নিন, উদাহরণস্বরূপ _একটি একক ব্যক্তিগত অবজেক্টের নীচে বা তার নীড় দিয়ে তাদের উপসর্গ করুন ।

var privateWorker = function() {
    return 1
}

var doSomething = function() {
    return privateWorker()
}

module.exports = {
    doSomething: doSomething,
    _privateWorker: privateWorker
}

7
আমি এটি এমন ক্ষেত্রে করেছি যেখানে পুরো মডিউলটি সত্যই ব্যক্তিগত হিসাবে ব্যবহৃত হয় এবং সাধারণ ব্যবহারের জন্য নয়। তবে সাধারণভাবে উদ্দেশ্য মডিউল আমি তা প্রকাশ করার কি আমি পরীক্ষার জন্য প্রয়োজন পছন্দ করা শুধুমাত্র যখন কোড পরীক্ষিত হচ্ছে। এটি সত্য যে শেষ পর্যন্ত এমন কিছু নেই যা কাউকে পরীক্ষার পরিবেশ নকল করে ব্যক্তিগত জিনিসগুলি পেতে বাধা দিতে পারে তবে যখন কেউ তাদের নিজস্ব অ্যাপ্লিকেশনটিতে ডিবাগিং করছে, আমি বরং সেগুলি প্রতীকগুলি দেখতে পাচ্ছি না যা হওয়ার দরকার নেই পাবলিক এপিআই এর অংশ। এই উপায়টির জন্য ডিজাইন করা হয়নি এজন্য এটির অপব্যবহার করার কোনও তাত্ক্ষণিক প্রলোভন নেই।
লুই

2
আপনি নেস্টেড সিনট্যাক্সটিও ব্যবহার করতে পারেন private ... ব্যক্তিগত : {কর্মী: কর্মী}}
জেসন

2
মডিউলটি যদি সমস্ত খাঁটি ফাংশন হয় তবে আমি এটি করার কোনও খারাপ দিক দেখছি না। আপনি যদি রাষ্ট্রটি ধরে রাখছেন এবং পরিবর্তন আনছেন তবে সাবধান হন ...
জিগজি

5

আমি এই উদ্দেশ্যে একটি এনপিএম প্যাকেজ তৈরি করেছি যাতে আপনি কার্যকর পেতে পারেন: প্রয়োজন থেকে

মূলত আপনি অ-সর্বজনীন পদ্ধতিগুলি এর দ্বারা প্রকাশ করেন:

module.testExports = {
    private_foobar1: private_foobar1,
    private_foobar2: private_foobar2,
    ...
}

দ্রষ্টব্য: অবশ্যই testExportsআপনি চান যে কোনও বৈধ নাম হতে পারে exports

এবং অন্য মডিউল থেকে:

var requireFrom = require('require-from');
var private_foobar1 = requireFrom('testExports', './path-to-module').private_foobar1;

1
আমি এই পদ্ধতির কোনও ব্যবহারিক সুবিধা দেখছি না। এটি "ব্যক্তিগত" চিহ্নগুলি আরও ব্যক্তিগত করে না। (যে কেউ requireFromসঠিক পরামিতি দিয়ে কল করতে পারে )) এছাড়াও, মডিউলটি textExportsলোড requireকরার আগে কোনও কল দ্বারা requireFromলোড করা থাকলে, requireFromফিরে আসবে undefined। (আমি এটি কেবল পরীক্ষা করেছি)) মডিউলগুলির লোড অর্ডার নিয়ন্ত্রণ করা প্রায়শই সম্ভব হলেও এটি সর্বদা ব্যবহারিক নয়। (এসও সংক্রান্ত কয়েকটি মোচা প্রশ্নের প্রমাণ হিসাবে)) এই সমাধানটি সাধারণত এএমডি-টাইপ মডিউলগুলির সাথে কাজ করে না। (আমি পরীক্ষার জন্য প্রতিদিন নোডে এএমডি মডিউলগুলি লোড করি))
লুই

এটি এএমডি মডিউলগুলির সাথে কাজ করা উচিত নয়! নোড.জেসগুলি কমন.জেস ব্যবহার করে এবং যদি আপনি এএমডি ব্যবহার করতে এটি পরিবর্তন করেন তবে আপনি এটি আদর্শের বাইরে করছেন doing
jemiloii

@ জিমিলিআইআই শত শত বিকাশকারী প্রতিদিন এএমডি মডিউলগুলি পরীক্ষা করতে নোড.জেএস ব্যবহার করে। এটি করার ক্ষেত্রে "আদর্শের বাইরে" কিছুই নেই। সর্বাধিক আপনি বলতে পারেন যে নোড.জেএসএএমএডি লোডার নিয়ে আসে না তবে এটি বেশি কিছু বলছে না, কারণ নোড তার লোডারটিকে প্রসারিত হুক সরবরাহ করে যা কোনও ফর্ম্যাট বিকাশকারী বিকাশ করতে পারে তা লোড করতে তার প্রসারকে প্রসারিত করে।
লুই 16

এটি আদর্শের বাইরে। যদি আপনাকে ম্যানুয়ালি একটি এএমডি লোডার অন্তর্ভুক্ত করতে হয় তবে এটি নোড.জেএস এর আদর্শ নয়। আমি খুব কমই নোড.জেএস কোডের জন্য এএমডি দেখতে পাই। আমি এটি ব্রাউজারের জন্য দেখতে পাব, তবে নোড। না, আমি বলছি না এটি করা হচ্ছে না, কেবল প্রশ্ন এবং এই উত্তরটিতে আমরা মন্তব্য করছি, এমডি মডিউলগুলি সম্পর্কে কিছুই বলবেন না। সুতরাং এমন কাউকে না জানিয়ে যে তারা একটি এমএডি লোডার, নোড রফতানি ব্যবহার করছে, এএমডি দিয়ে কাজ করা উচিত নয়। যদিও আমি লক্ষ করতে চাই না, সাধারণ j এস রফতানির সাথে বেরিয়ে আসতে পারে। আমি কেবল আশা করি যে একদিন আমরা সকলেই কেবল একটি রফতানি পদ্ধতি ব্যবহার করতে পারি।
জিমিলোই

4

আমি একটি অতিরিক্ত ফাংশন যুক্ত করেছি যার নাম আমি অভ্যন্তরীণ () এবং সেখান থেকে সমস্ত ব্যক্তিগত ফাংশন ফিরিয়ে । এই অভ্যন্তরীণ () ফাংশনটি তখন রফতানি করা হয়। উদাহরণ:

function Internal () {
  return { Private_Function1, Private_Function2, Private_Function2}
}

// Exports --------------------------
module.exports = { PublicFunction1, PublicFunction2, Internal }

আপনি এই জাতীয় অভ্যন্তরীণ ফাংশন কল করতে পারেন:

let test = require('.....')
test.Internal().Private_Function1()

আমি এই সমাধানটি সবচেয়ে পছন্দ করি কারণ:

  • কেবলমাত্র একটি ফাংশন অভ্যন্তরীণ () সর্বদা রফতানি হয়। এই অভ্যন্তরীণ () ফাংশনটি সর্বদা ব্যক্তিগত ফাংশনগুলি পরীক্ষার জন্য ব্যবহৃত হয়।
  • এটি কার্যকর করা সহজ
  • উত্পাদন কোডের উপর কম প্রভাব (শুধুমাত্র একটি অতিরিক্ত ফাংশন)

2

আমি @ বারউইন উত্তর অনুসরণ করেছি এবং পরীক্ষা করেছিলাম কীভাবে রিওয়্যার মডিউল দিয়ে ইউনিট পরীক্ষা করা যায় । আমি নিশ্চিত করতে পারি যে এই সমাধানটি কেবল কার্যকরভাবে কাজ করে।

মডিউলটি দুটি অংশে আবশ্যক - সর্বজনীন এক এবং ব্যক্তিগত একটি। জনসাধারণের কাজের জন্য আপনি এটি স্ট্যান্ডার্ড উপায়ে করতে পারেন:

const { public_foobar3 } = require('./foobar');

ব্যক্তিগত সুযোগের জন্য:

const privateFoobar = require('rewire')('./foobar');
const private_foobar1 = privateFoobar .__get__('private_foobar1');
const private_foobar2 = privateFoobar .__get__('private_foobar2');

বিষয়টি সম্পর্কে আরও জানতে, আমি সম্পূর্ণ মডিউল পরীক্ষার সাথে একটি কার্যকারী উদাহরণ তৈরি করেছি, পরীক্ষায় ব্যক্তিগত এবং জনসাধারণের সুযোগ অন্তর্ভুক্ত রয়েছে।

আরও তথ্যের জন্য আমি আপনাকে নিবন্ধটি পরীক্ষা করার জন্য উত্সাহিত করছি ( https://medium.com/@macsikora/how-to-test-private-function-of-es6-module-fb8c1345b25f ), এতে কোডের নমুনা রয়েছে।


2

আমি জানি যে অগত্যা আপনি যে উত্তরটি সন্ধান করছেন তা নয়, তবে আমি যা খুঁজে পেয়েছি তা হল বেশিরভাগ সময় যদি কোনও ব্যক্তিগত ফাংশন পরীক্ষার জন্য মূল্যবান হয় তবে এটি নিজের ফাইলটিতে থাকা মূল্যবান।

যেমন জনসাধারণের মতো একই ফাইলে ব্যক্তিগত পদ্ধতি থাকার পরিবর্তে, এর মতো ...

src / জিনিস / PublicInterface.js


function helper1 (x) {
    return 2 * x;
}

function helper2 (x) {
    return 3 * x;
}

export function publicMethod1(x) {
    return helper1(x);
}

export function publicMethod2(x) {
    return helper1(x) + helper2(x);
}

... আপনি এটিকে এভাবে ভাগ করে নিন:

src / জিনিস / PublicInterface.js

import {helper1} from './internal/helper1.js';
import {helper2} from './internal/helper2.js';

export function publicMethod1(x) {
    return helper1(x);
}

export function publicMethod2(x) {
    return helper1(x) + helper2(x);
}

src / জিনিস / অভ্যন্তরীণ / helper1.js

export function helper1 (x) {
    return 2 * x;
}

src / জিনিস / অভ্যন্তরীণ / helper2.js

export function helper2 (x) {
    return 3 * x;
}

এইভাবে, আপনি সহজেই রিওয়্যার এবং অন্যান্য "যাদু" ব্যবহার না করে পরীক্ষা করতে helper1এবং helper2যেমনটি করতে পারেন (যা আমি খুঁজে পেয়েছি, ডিবাগ করার সময় তাদের নিজস্ব ব্যথা পয়েন্ট রয়েছে বা যখন আপনি টাইপস্ক্রিপ্টের দিকে এগিয়ে যাওয়ার চেষ্টা করছেন, তখন দরিদ্রের কথা উল্লেখ না করে নতুন সহকর্মীদের জন্য বোধগম্যতা)। এবং এগুলি একটি সাব-ফোল্ডার নামে পরিচিত internal, বা এর মতো অন্য কিছু, অযৌক্তিক জায়গায় এগুলির দুর্ঘটনাজনিত ব্যবহার এড়াতে সহায়তা করবে।


দ্রষ্টব্য: "ব্যক্তিগত" পদ্ধতি আরেকটি সাধারণ সমস্যা যে আপনি যদি পরীক্ষা করতে চান publicMethod1এবং publicMethod2এবং সাহায্যকারী উপহাস, আবার, আপনি সাধারণত বৈদ্যুতিক তার লাগানো ভালো কিছু যে কি করতে হবে। তবে, যদি সেগুলি পৃথক ফাইলে থাকে তবে আপনি এটি করতে প্রক্সিয়ার ব্যবহার করতে পারেন , যা রিওয়াইরের বিপরীতে আপনার বিল্ড প্রক্রিয়াতে কোনও পরিবর্তনের প্রয়োজন হয় না, পড়া এবং ডিবাগ করা সহজ এবং টাইপস্ক্রিপ্টের সাথেও ভাল কাজ করে।


1

পরীক্ষার জন্য ব্যক্তিগত পদ্ধতি উপলব্ধ করার জন্য, আমি এটি করি:

const _myPrivateMethod: () => {};

const methods = {
    myPublicMethod1: () => {},
    myPublicMethod2: () => {},
}

if (process.env.NODE_ENV === 'test') {
    methods._myPrivateMethod = _myPrivateMethod;
}

module.exports = methods;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.