tarjetas son que programar ntag215 inteligentes etiquetas crear bar ios swift xctest xctestcase

ios - son - Cómo ejecutar un código de configuración de una sola vez antes de ejecutar cualquier XCTest



programar etiquetas nfc (4)

De clases y métodos de prueba de escritura :

Opcionalmente, también puede agregar métodos personalizados para la configuración de la clase (+ (void)setUp) configuración (+ (void)setUp) y desmontaje (+ (void)tearDown) , que se ejecutan antes y después de todos los métodos de prueba en la clase.

En Swift serían métodos de class :

override class func setUp() { super.setUp() // Called once before all tests are run } override class func tearDown() { // Called once after all tests are run super.tearDown() }

Tengo el siguiente problema. Quiero ejecutar un fragmento de código antes de que se ejecuten todas las clases de prueba. Por ejemplo: no quiero que mi juego use el Soundlet del singleton durante la ejecución, sino el SilentSoundEngine. Me gustaría activar SilentSoundEngine una vez, no en todas las pruebas. Todas mis pruebas se ven así:

class TestBasketExcercise : XCTestCase { override func setUp() { SilentSoundEngine.activate () // SoundEngine is a singleton } // The tests }

-Editar- La mayoría de las respuestas están dirigidas a proporcionar una superclase personalizada para el TestCase. Estoy buscando una forma más general y más limpia de proporcionar el entorno que todas las pruebas necesitan ejecutar. ¿No hay una función "principal" / característica de Appdelegate en algún lugar para las pruebas?


Si creas una superclase para que tu caso de prueba se base, entonces puedes ejecutar una configuración universal en la superclase y hacer la configuración específica que necesites en las subclases. Estoy más familiarizado con Obj-C que con Swift y todavía no he tenido la oportunidad de probar esto, pero debería estar cerca.

// superclass class SuperClass : XCTestCase { override func setUp() { SilentSoundEngine.activate () // SoundEngine is a singleton } } // subclass class Subclass : Superclass { override func setUp() { super.setup() } }


realmente no lo entiendo pero si busca un método que solo se ejecute una vez ... - suena bien O lo que definitivamente funciona es + cargar

EDITAR:

ya que no puede anular más la carga, si init no es lo que necesita, use dispatch_once en init


TL; DR:
Como se indica here , debe declarar un NSPrincipalClass en su lista de información de objetivos de prueba. Ejecute todo el código de configuración única dentro del inicio de esta clase, ya que "XCTest crea automáticamente una instancia única de esa clase cuando se carga el paquete de prueba", por lo tanto, todo el código de configuración única se ejecutará una vez al cargar el paquete de prueba

Un poco más detallado:

Para responder a la idea en su edición primero:

Afaik, no hay main() para el paquete de prueba, ya que las pruebas se inyectan en su objetivo principal en ejecución, por lo tanto, tendría que agregar el código de configuración de una sola vez en el main() de su objetivo principal con una compilación el tiempo (o al menos un tiempo de ejecución) comprueba si el objetivo se utiliza para ejecutar pruebas. Sin esta comprobación, SilentSoundEngine el riesgo de activar SilentSoundEngine cuando ejecute el objetivo normalmente, lo que creo que no es deseable, ya que el nombre de la clase implica que este motor de sonido no producirá ningún sonido y, honestamente, ¿quién quiere eso? :)

Sin embargo, hay una característica similar a la de AppDelegate llegaré a eso al final de mi respuesta (si está impaciente, está bajo el encabezado "Otro enfoque (más específico de XCTest)").

Ahora, dividamos esta pregunta en dos problemas centrales:

  1. ¿Cómo puede asegurarse de que el código que desea ejecutar exactamente una vez al ejecutar las pruebas se ejecute realmente una vez al ejecutar las pruebas?
  2. ¿Dónde debería ejecutar ese código, para que no se sienta como un truco feo y, por lo tanto, funciona sin que tenga que pensar en ello y recordar los pasos necesarios cada vez que escriba un nuevo conjunto de pruebas?

Respecto al punto 1:

Como @Martin R mencionó correctamente en sus comentarios a esta respuesta a su pregunta, anular +load ya no es posible a partir de Swift 1.2 (que ahora es historia antigua: D), y dispatch_once() ya no está disponible en Swift 3 .

Una aproximación

Cuando intentas usar dispatch_once todos modos, Xcode (> = 8) es como siempre muy inteligente y sugiere que deberías usar globales iniciados de manera perezosa. Por supuesto, el término global tiende a hacer que todos se dejen llevar por el miedo y el pánico, pero, por supuesto, puede limitar su alcance haciéndolos privados / filiprivados (que hacen lo mismo con las declaraciones a nivel de archivo), para no contaminar su espacio de nombres .

Imho, en realidad son un patrón muy bonito (aún así, la dosis hace que el veneno ...) que puede verse así, por ejemplo:

private let _doSomethingOneTimeThatDoesNotReturnAResult: Void = { print("This will be done one time. It doesn''t return a result.") }() private let _doSomethingOneTimeThatDoesReturnAResult: String = { print("This will be done one time. It returns a result.") return "result" }() for i in 0...5 { print(i) _doSomethingOneTimeThatDoesNotReturnAResult print(_doSomethingOneTimeThatDoesReturnAResult) }

Esto imprime:

Esto se hará una vez. No devuelve un resultado.
Esto se hará una vez. Devuelve un resultado.
0
resultado
1
resultado
2
resultado
3
resultado
4
resultado
5
resultado

Nota al margen: Curiosamente, los fondos privados se evalúan antes de que comience el ciclo, lo que puede ver porque, de no ser así, el 0 sería la primera impresión. Cuando comente el bucle de salida, seguirá imprimiendo las dos primeras líneas (es decir, evaluará los permisos).
Sin embargo, creo que este es un comportamiento específico en el patio de recreo, porque como se indica here y here , los indicadores globales normalmente se inicializan la primera vez que se hace referencia en algún lugar, por lo tanto, no deben evaluarse cuando se comenta.

Otro enfoque (más específico de XCTest)

(Esto realmente resuelve tanto el punto 1 como el 2 ...)

Como afirma la compañía de Cupertino here , hay una manera de ejecutar un código de configuración de prueba previa una vez.

Para lograr esto, creas una clase de configuración ficticia (¿quizás la llamas TestSetup?) Y pones todo el código de configuración de una sola vez en su init:

class TestSetup: NSObject { override init() { SilentSoundEngine.activate() } }

Tenga en cuenta que la clase tiene que heredar de NSObject, ya que Xcode intenta crear una instancia de la "instancia única de esa clase" utilizando +new , por lo que si la clase es una clase Swift pura, esto sucederá:

*** NSForwarding: warning: object 0x11c2d01e0 of class ''YourTestTargetsName.TestSetup'' does not implement methodSignatureForSelector: -- trouble ahead Unrecognized selector +[YourTestTargetsName.TestSetup new]

Luego, declara esta clase como PrincipalClass en su archivo Info.plist de paquetes de prueba:

Tenga en cuenta que debe utilizar el nombre de clase completo (es decir, YourTestTargetsName.TestSetup en comparación con solo TestSetup), por lo que Xcode encuentra la clase (Gracias, zneak ...).

Como se indica en la documentación de XCTestObservationCenter, "XCTest crea automáticamente una única instancia de esa clase cuando se carga el paquete de prueba", por lo que todo su código de configuración de una sola vez se ejecutará en el inicio de TestSetup al cargar el paquete de prueba.