QUnit заглушение методов на зависимости ломает тесты против этой зависимости - PullRequest
0 голосов
/ 28 сентября 2018

В Google Apps Script я тестирую юнит-приложение, над которым я работаю, , используя QUnit , используя тестируемую разработку.

Кодпод тестом

Сейчас я работаю над полным тестированием, а затем разрабатываю следующую функцию:

/**
 * 
 *  Creates a Sheet from a long string of data
 *  @param { string } data : the long string of data
 *  @returns { Sheet } the newly-created Sheet
 **/
function createSheetFrom(data) { 
  // if data is not in the form of a string, we've got a problem
  if (data !== data.toString())
    throw TypeError("Data must be in the form of a string")
  // parse the data into SheetData
  sheetData = SheetData.parse(data);
  // create a new Sheet
  newSheet = SPREADSHEET.insertSheet(sheetData.projectName)
  // create title rows for it
  createTitleRow(sheet)

  return newSheet
}

, где SPREADSHEET - сценарий Spreadsheetприкреплен, сохранен как глобальная переменная для удобства.

Эта функция зависит, среди прочего, от той, которая находится прямо под ней, которая была успешно полностью протестирована и разработана:

/** 
 *  Creates a title row for the spreadsheet
 *  
 *  @param { Sheet } sheet : the spreadsheet to create a title row for
 *  @returns { Sheet } the sheet for chaining purposes
 **/
function createTitleRow(sheet) { 
  // declare the titles
  var titles = ["File", "Total Cyclomatic Complexity", "Already unit-tested?", "Status Date"];
  // insert a row right at the beginning
  sheet.insertRows(1);
  var titleRow = sheet.getRange(1, 1, 1, titles.length);
  // set some values on titleRow
  titleRow.setValues(titles);
  titleRow.setHorizontalAlignment(CENTER)
  return sheet;
}

Тесты:

Мой тест против createSheetFrom выглядит следующим образом:

function testCreateSheetFrom() { 
  var globalSpreadsheet // for storing the state of SPREADSHEET
  var sheet // a stub Sheet

  var createTitleRowCalls = []
  var titleRowFunction


  QUnit.test("testing createSheetFrom with 'file contents' that is simply one line of output",
             function() { 
               throws(function() { 
                 val = createSheetFrom("3 blah funcName c:/blah/foo/bar");
               }, "Exception caught successfully")  
             })


}

... и тест против createTitleRow:

function testCreateTitleRow() { 
  var sheet // spy for the Sheet object from the Google Spreadsheet API


  QUnit.testStart(function() { 
    // create a sheet spy
    sheet = {
      insertRowsCalls : [],
      insertRows : function(idx) { 
        Logger.log("insertRows called")
        this.insertRowsCalls.push({ args : idx });
      },
      getRangeCalls : [],
      range : {
        setValuesCalls : [],
        setValues : function(arr) { 
          if (!Array.isArray(arr)) return;
          // simply record the args that this was called with
          this.setValuesCalls.push({ args : arr });
        },
        setHorizontalAlignment: function(setting) {} 
      },
      // method stub
      getRange : function(r0,c0,r1,c1) { 
        Logger.log('getRange called')
        this.getRangeCalls.push({ args : Array.prototype.splice.call(arguments, 0) });
        return this.range;
      }
    };

  })

  QUnit.test("testing createTitleRow",
             function() { 

               // hit the method under test
               val = createTitleRow(sheet);
               // the methods better have been hit
               equal(sheet.insertRowsCalls.length, 1, "sheet.insertRows only got invoked once")
               ok(sheet.getRangeCalls, "sheet.getRange() got invoked at least once")
               ok(sheet.getRangeCalls.length)
               deepEqual(sheet.getRangeCalls[0].args.filter(function(val, key) { return key < 3 }), [1,1,1], "the right arguments got sent to sheet.getRange()")
               setValuesCalls = sheet.range.setValuesCalls
               ok(setValuesCalls.length, "A call was made to sheet.range.setValues")
               equal(setValuesCalls[0].args.length, 4, "The call was made with four args, as we expect")
               // sheet better have been returned
               equal(val, sheet, "createTitleRow() returns the sheet for testing, as promised")
             })

}

Все тесты проходят:

enter image description here

Тем не менее, когда я добавляю к тестам против createSheetFrom следующий тест на работоспособность, заглушая createTitleRow в настройке, возвращая его обратно к реальному самомув разрыве оба теста против createSheetFrom и createTitleRow break!

Код для этого теста на разрыв:

QUnit.testStart(function() { 
        // create a spy out of sheet


    sheet = {

    }
    // replace SPREADSHEET with a spy
    globalSpreadsheet = SPREADSHEET
    SPREADSHEET = {
      insertSheetCalls : [],
      insertSheet : function(str) { 
        this.insertSheetCalls.push({ args: str })
        return sheet
      }

    }
    // stub out the dependencies
    titleRowFunction = createTitleRow
    createTitleRow = function(sheet) { 
      createTitleRowCalls.push({ args : sheet })
      return sheet
    }

  })

  QUnit.test("SanityTesting createSheetFrom", 
             function() { 
               projectName = "main"

               complexity = 3
               packageName = "main"
               funcName = "SetContext"
               filename = "main.go"

               fileContents = createFileContents(projectName,
                                                 createLineOfTextFrom(complexity, packageName, funcName, "C:/Users/mwarren/Desktop/" + filename))

               sheet = createSheetFrom(fileContents)
               ok(SPREADSHEET.insertSheetCalls.length, "SPREADSHEET.insertSheet got called")
             })

  QUnit.testDone(function() { 
    // set SPREADSHEET back
    SPREADSHEET = globalSpreadsheet
    // set the dependencies back 
    createTitleRow = titleRowFunction
  })

Скриншоты тестовых регрессий:

enter image description here

Я не знаю, почему происходят эти регрессии, тем более, что я откладываю изменения, которые я внес в настройку ...

Состояния используемых объектов переносятся в другие тестовые случаи в других тестовых функциях, несмотря на то, что я использовал testDone для установки состоянийобъектов назад.Теперь это происходит и в других тестовых примерах

...