1

我试图找出确定我是否正在为 Web 应用程序运行 UI 测试的最佳方法。我尝试这样做的原因是因为如果我正在运行 UI 测试,这些测试的唯一目的是确保 UI 正常工作并且要做到这一点,它们应该针对模拟 API 运行(我们有一个单独的集合集成测试以确保 UI 和真正的后端 API 一起正常工作)。此外,模拟 API 调用将使测试测试运行得更快,这是模拟它们的另一个原因。我认为这些 UI 的“单元测试”。

我也不想拥有相同代码库的 2 个单独副本,其中除了 UI 测试版本包含模拟 UI 测试正常运行所需的所有必需调用的 javascript 文件之外,所有内容都相同。如果我能够弄清楚我在 UI 测试模式下运行应用程序,那么我将能够知道是否包含 javascript 文件来模拟调用。

有没有“标准”或“公认”的方式来做这样的事情?

4

2 回答 2

0

当您开始运行测试时 - 在数据库中提出一个标志并拥有一个可以调用以检查该标志的服务。确保在测试结束后关闭该标志。

于 2013-08-06T20:40:28.907 回答
0

The short answer to "Is there any standard or accepted way to do something like this?" would be: no.

This is mainly because you don't want your UI to know this kind of information at all. You want your UI to just be your UI. As soon as your UI starts taking some decisions based on whether it's in "test mode" or "production mode", you embark on a slippery slope that will ultimately lead to a nightmare code-base.

This does not mean your problem cannot be solved; just that the solution should be approached in a different way. I'll first explain the general principles without any language specifics, then provide some guidelines for javascript.

General Principles

The only reason for you to be struggling with this is that your UI is too tightly coupled to the API.

The solution happens to be exactly the same as any situation when you wish to use mocks.

  1. Program to an interface, not an implementation. (Ensure your UI binds only to an abstraction of the API - not the "true/production API".)
  2. Separate instantiation from interaction. (Don't let your UI create any of its API dependencies, because that binds it to a specific implementation - rather provide interface on the UI for it to be given the specific API instance it should use.)

Program to an interface

First note that the above phrase does not mean your language needs to support an "interface" construct. (It's just an unfortunate choice of name by some language implementors.)

  • Define a base class/object which defines each of the methods/messages that your API should support. (However, none of these will actually be implemented on the base class/object.)
  • Your UI should have a variable/field/reference to the APIInterface.
  • Your UI will call the methods it needs from the API via the interface reference. E.g. APIRef.DoMethod1(...) or APIRef->DoMethod1(...) or [APIRef DoMethod1:...] etc.

Separate instantiation from interaction

The thing to avoid here is:

CreateUI {
  APIRef = CreateAPI;
}

The above binds your UI to a specific implementation, and forces you to include those files/dependencies in your UI code. You would rather have your UI be told which API to use. E.g.

CreateUI(APIInterface APIToUse) { //NB: Notice that the type use to refer 
                                  //to the API is the abstract base type 
                                  //defined earlier (keeping to the "Program 
                                  //to an interface" principle).
  APIRef = APIToUse;
}
//or
SetAPI(APIInterface APIToUse) {
  APIRef = APIToUse;
}

Now your production application could look something like this:

API = CreateTrueAPI;
UI = CreateUI(API);

Whereas your test application could look something like this:

API = CreateMockAPI;
UI = CreateUI(API);

Notice how with this solution, your UI doesn't have a clue about "test mode" or "production mode". It just uses the API it is given. The only thing that knows about the "test mode" (in a manner of speaking) and the mock API is the test application.

Applying the principles to Javascript

First, let me state for the record: although I am familiar with the language principles of Javascript, I have never done JS development. So there may be some unforeseen complications. However, in the worst case, with a little tweaking and research, I'm sure you'll figure something out.

Javascript supports duck-typing which basically means you can send any message to any object, and at runtime the object will decide if it can actually process the message. You lose out on compile-time checking that you haven't made any typo errors, but as I understand it: you don't really need to define the abstract base interface at all.
So...

  • Simply ensure your UI has a reference to an API object.
  • Ensure your UI doesn't include any API implementation files (neither the true/production version nor the mock version).
  • In your production host create the true API, create the UI and pass the true API to the UI.
  • In your test host create the mock API, create the UI and pass the mock API to the UI.
于 2013-11-08T20:54:26.633 回答