【问题标题】:Testing stateful classes测试有状态的类
【发布时间】:2017-03-16 19:27:33
【问题描述】:

我有一个可以加载、关闭或重命名图像的类(至少现在,将来会有更多打开文件的操作)。

我已经用 Facade 模式实现了它(我想是的)。

当我尝试为它编写测试时,我很快注意到我需要使用不同的前置条件来测试它(例如,在调用某个方法之前加载图像时)。而且测试的数量是巨大的,当我添加新的操作时会很快增长。据我了解,这些不是单元测试,而是端到端测试。

我是 TDD 新手,谁能告诉我进行如此复杂的测试是否正常?

我期待我的班级责任过多的答案,但让我们想想替代方案:

// pseudo-code

// #1 - my way
function onRenameButtonClick(newName) {
  imageFacade.rename(newName)
}

// #2 - the other way
function onRenameButtonClick(newName) {
  if (imageController.isOpened()) {
    imageRenamer.rename(imageController.image, newName)
  }
}

最后我仍然需要测试#2 的正确行为,它仍然会涉及使用不同的前置条件。

您如何处理此类情况?这是正常的还是我做错了什么?

P。 S. 这里是我的门面类的骨架,注意config 中有纯函数,做实际工作,actions 正在拼接这些纯函数并根据状态触发事件。

function makeImageWTF(loader, renamer) {
  return {
    state: {
      image: null,
      filePath: null,
      isLoading: false
    },
    config: {
      loader,
      renamer
    },
    triggers: {
      opening: new Bus(),
      opened: new Bus(),
      closed: new Bus(),
      renamed: new Bus(),
      error: new Bus()
    },
    actions: {
      open: function(path) {},
      close: function() {},
      rename: function(newName) {}
    }
  }
}

这是一个测试框架

describe('ImageWTF', function() {
  describe('initial state', function() {
    it('should be that', function() {
      var wtf = makeImageWTF()
      assert.deepEqual({
        image: null,
        filePath: null,
        isLoading: false,
      }, wtf.state)
    })
  })

  describe('#open(path)', function() {
    it('sets isLoading')
    it('calls config.loader with path')
    it('sets image, fileName')
    it('triggers loading, loaded or error')
    it('clears isLoading')
  })

  describe('#close()', function() {
    describe('when image is opened', function() {
      it('resets image')
      it('triggers closed')
    })

    describe('when image is NOT opened', function() {
      it('triggers error')
    })    
  })

  describe('#rename()', function() {
    describe('when image is opened', function() {
      it('calls config.renamer with oldName and newName')
      it('sets fileName')
      it('triggers renamed')
    })

    describe('when image is NOT opened', function() {
      it('triggers error')
    })
  })
})

【问题讨论】:

    标签: unit-testing end-to-end


    【解决方案1】:

    (单元)测试就像生产代码一样——它们可能会变得复杂。但目标当然应该是让它们尽可能简单。

    如果您的代码还没有测试,我建议您开始编写测试以涵盖最重要的用例。一旦你有了这些工作,你就可以重构它们。但对我来说,主要关注点是进行测试,沿着这条路走下去你会学到很多东西。

    如果它们从一开始就不是“单元测试”,我不会太在意,请更改它们以适合您的应用程序。

    尽量不要将测试与生产代码硬耦合,因为您希望灵活地重构生产代码而不同时更改测试(当然,反之亦然)。对我来说,单元测试实际上是为了让更改和重构代码变得容易和快速。它们不会捕获您应用程序中的所有错误或行为 - 因为您还需要关注其他类型的测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-07
      相关资源
      最近更新 更多