jueves, 31 de enero de 2019

Progress - ¿Qué es ABL?

 ¿Qué es ABL?
Advanced Business Language (ABL) es un lenguaje de programación de procedimientos de alto nivel que ayuda a los desarrolladores
para desarrollar aplicaciones opcionalmente utilizando su propia base de datos relacional integrada y herramienta de programación. Estas
Las aplicaciones son portátiles en todos los sistemas informáticos y permiten el acceso a varias fuentes de datos populares sin necesidad de
Tener que aprender los métodos de acceso a los datos subyacentes. Esto significa que el usuario final de estos productos puede ser
Desconociendo la arquitectura subyacente.
Al combinar un lenguaje de cuarta generación y una base de datos relacional, ABL permite a los desarrolladores de aplicaciones
administre los datos relacionales de manera que modele cómo funciona la empresa. Un programador e incluso usuarios finales.
puede hacer prototipos rápidos utilizando las herramientas integradas y GUI del entorno de desarrollo.

ABL es una herramienta versátil y extraordinariamente poderosa. No solo puedes usarlo para programar aplicaciones, sino que
puede crear muchas de las herramientas que usa para ayudar a crear y admitir esas aplicaciones. La mayor parte del desarrollo.
Las herramientas que utiliza para desarrollar aplicaciones OpenEdge® están escritas en ABL.

Progress

Es una Base de Datos.

Es una colección de información interrelacionada así como un conjunto de programas para tener acceso a dicho datos, usada para las aplicaciones de una organización. El objetivo de una base de datos es proporcionar un entorno que sea conveniente y eficiente para extraer y almacenar información. Algunos de los problemas que se presentan cuando no se utiliza una base de datos son:

 • Redundancia e inconsistencia de los datos: Debido a que los archivos de programas de aplicaciones son creados por diferentes personas a través del tiempo, puede ocurrir que los archivos tengan diferente formato o se encuentren duplicados, de la misma manera puede ocurrir que los programas para acceder a la información se encuentre en más de un sitio.
• Desarrollos de múltiples aplicaciones para la recuperación de la información: Un sistema de información basado en Base de datos pretende desarrollar aplicaciones de uso general para la recuperación de la información, tratando de establecer estándares tanto en las aplicaciones como en la forma de almacenar los datos.
• Proliferación de archivos: Pretende aislar los datos de las aplicaciones para un mejor control de tal manera que no se tenga que modificar la estructura de la Base de datos cuando se desarrolle una nueva aplicación.
• Evitar el acceso simultaneo de los usuarios a la misma información: Control de acceso a la información ara evitar su inconsistencia, permitiendo que solamente un usuario tenga acceso a los datos y colocando candados hasta que estos sean liberados.
• Problemas de seguridad: Implantar las restricciones de seguridad para tener acceso a los datos.
• Problemas de integridad: Colocar restricciones de consistencia de datos.

Sistema de información: Conjunto de elementos interrelacionados que tiene como fin suministrar a los usuarios la información requerida para la toma de decisiones.

Sistema administrador de Base de datos(Data Base Manager System): Es un conjunto de herramientas integrado que proporciona el entorno para un eficiente almacenamiento y recuperación de la información.

Abstracción de los datos Un objetivo importante en un sistema de Base de datos es proporcionar a los usuarios una visión abstracta de los datos; el sistema esconde ciertos detalles de cómo se almacenan y mantiene los datos.

Nivel físico: En este nivel se describe como están los datos realmente almacenados, se describen en detalle las estructuras de datos complejas.

• Nivel conceptual: En este nivel se describe que datos son almacenados realmente y las relaciones que existen entre ellos. Este nivel lo emplean los administradores de la Base de datos ya que ellos deben decidir que información es la que se almacena.
• Nivel de visión: Este nivel es empleado por los usuarios ya que ellos solamente necesitan ver los datos con los que va a trabajar.




Para Conectarse a una base de datos en Progress: 
• Seleccionar desde el menú de File y la opción OPEN, después Database. se busca la base de datos realizada por tí. 
• También para conectar la Tecla F3. 

 Para Desconectarse de una Base de Datos en Progress:
 • En la Aplicación de Data Dictionary. 
• Se selecciona la opción de database 
• Después elegir la opción de Disconnect. 
• También para desconectar la Tecla F8.



El Metaesquema

 • Es un conjunto de tablas relacionadas, la cual nos indica la descripción de la estructura de una base de datos.
• Contiene la definición para describir los componentes de una base de datos, tales como tablas, campos, índices entre otros.
 • También contiene elementos y mensajes de validación.
 • Es el corazón de la base de datos en PROGRESS.
• Al momento de crear una base de datos “EMPTY” , se tiene toda la información básica necesaria para crear el esquema de una aplicación.


Definición de una base de datos

• Nombre de Tablas, Campos e Índices: o Máximo de 32 caracteres de largo. o Debe de comenzar por un carácter alfabético (A-Z, o a-z). 9 Caracteres alfabéticos (A-Z o a-z). 9 Dígitos (0-9). 9 Caracteres especiales($,&,%,-). o Es insensitivo al uso de mayúsculas.

Crear Tabla


  •  Table Name 
  •  Etiqueta 
  •  Descripción 
  •  Nombre para “DUMP”.
  •   TRIGGERS y Atributos de traducción. 
  •  Validación de borrado.
  •   Hidden
  •   Frozen 
  •  String Attrs. 
  •  Data server 
  •  Check CRC 
  •  Overdrable





Broker

Un intermediario es el proceso de base de datos principal que crea una instancia y administra el área de memoria compartida de un multiusuario.
base de datos. Realiza diversas tareas en una base de datos en ejecución. Un broker coordina toda la conexión de la base de datos.
Las solicitudes y los servidores recuperan y almacenan datos en nombre de los clientes. El proceso de intermediación bloquea la base de datos.
para evitar que cualquier otro agente o proceso de un solo usuario lo abra.

Server 
Los servidores son procesos de base de datos que acceden a la base de datos a través de la memoria compartida en nombre de uno o más
clientes remotos El agente los inicia, según sea necesario, para manejar los clientes remotos entrantes. Los servidores ABL son los
servidores, que solo admiten clientes remotos de OpenEdge Advanced Business Language (ABL).




Client
Un proceso de cliente podría ser un cliente ABL u otro tipo de cliente OpenEdge, como un Cliente Abierto. Clientela
acceder a la lógica de negocios de una aplicación solicitando un servicio de una Entidad de Negocios (o Tarea de Negocios)
o Business Workflow). Los clientes pueden consultar, agregar, eliminar o modificar datos en una base de datos. Hay dos tipos de
clientes:

• Remoto (Red): los clientes remotos pueden ser locales o remotos, pero no pueden conectarse a una base de datos
directamente, por lo que debe utilizar un servidor. Los clientes de la red acceden a la base de datos a través de un proceso de servidor que
El agente comienza a través de una conexión de red. La red o cliente remoto no tiene acceso a las redes compartidas.
Memoria, y debe comunicarse con un proceso de servidor.

Nota: OpenEdge RDBMS trata a los clientes SQL como clientes remotos, incluso si residen en la misma máquina
como la base de datos.

• Autoservicio: los clientes de autoservicio residen en la misma máquina que el intermediario, accede directamente a la base de datos
a través de la memoria compartida, realice las funciones del cliente y del servidor en un proceso y ejecute la aplicación
lógica directamente

Background processes
Background processes son procesos de base de datos que se ejecutan en segundo plano. Los procesos mejoran la base de datos.
Desempeño y mantenimiento de la integridad de los datos en caso de falla del sistema o falla de los medios.
Hay cuatro procesos de fondo:
• Before-image Writer (BIW): escribe buffers de BI completos en los archivos de BI en el disco.
• After-image Writer (AIW): escribe buffers AI completos en los archivos AI en el disco.
• Escritor asíncrono de páginas (APW): escribe bloques de bases de datos modificados en el disco.
• Watchdog (PROWDOG): se limpia después de que los clientes de autoservicio terminados incorrectamente y el control remoto
Clientes de servidores perdidos.

AppServers

OpenEdge AppServer es un motor de transacciones basado en estándares que proporciona una base confiable para
Transacciones seguras de alto volumen e independencia de la interfaz de usuario.
Al dividir las aplicaciones y separar la lógica de procesamiento de negocios de la lógica de la interfaz de usuario, puede
Accede a las aplicaciones a través de prácticamente cualquier interfaz. La lógica empresarial centralizada mejora la productividad al
proporcionándole un único punto para gestionar el acceso a los datos y procesos. Dado que la lógica de negocio se ejecuta
por separado de la interfaz de usuario de la aplicación, se puede utilizar una amplia variedad de clientes para ampliar la compatibilidad con
Estrategias agresivas de crecimiento.
Figura 4: OpenEdge AppServer Technology

Algunos beneficios clave de OpenEdge AppServer incluyen:
• Proporciona acceso directo a la misma lógica empresarial desde una amplia variedad de OpenEdge y la industria común
Tecnología, que le ofrece muchas opciones sobre cómo interactúa su aplicación con sus usuarios finales.
• Desconecta la ubicación del hardware físico de su aplicación, lo que proporciona flexibilidad para configurar y
manteniendo su entorno operativo.
• Admite el procesamiento asíncrono para un tiempo de respuesta de la aplicación más rápido.
• Garantiza la confiabilidad al ofrecer balanceo de carga y failover Reduce los requisitos de hardware al proporcionar
administración del Estado.







Función TRIM

Elimina los espacios en blanco iniciales y finales, u otros caracteres especificados, de una expresión CHARACTER o LONGCHAR. El tipo de datos del valor devuelto coincide con el tipo de datos de la expresión pasada a la función.


DISPLAY LENGTH("holaffff") LABEL "Byte Length".


DEFINE VARIABLE  i AS INTEGER NO-UNDO.
DEFINE VARIABLE  cvarcuentas AS CHARACTER NO-UNDO.
cvarcuentas = "19.1000.1200".
IF num-entries(cvarcuentas,".") <> 2 THEN
      DO i = 1 TO NUM-ENTRIES(cvarcuentas):
        display ENTRY(i,cvarcuentas).
      END.
ELSE DO:
      display num-entries(cvarcuentas,".").
END.


Using UNDO, LEAVE on a block


En esta sección, prueba un ejemplo que usa UNDO, LEAVE en un bloque. Para deshacer y dejar el bloque que actualiza la tabla OrderLine

FOR EACH ttOline WHERE ttOline.TransType = "":
    ...
    /* Find corresponding bUpdateOline */
    FIND OrderLine WHERE OrderLine.OrderNum = ttOline.OrderNum AND
      OrderLine.LineNum = ttOline.LineNum EXCLUSIVE-LOCK.
    ...
    BUFFER-COPY bUpdateOline TO OrderLine. /* Save OrderLine changes. */
    RELEASE OrderLine.

    /* Re-find the db record to capture any changes made by a trigger. */
    FIND OrderLine WHERE OrderLine.OrderNum = bUpdateOline.OrderNum AND
      OrderLine.LineNum = bUpdateOline.LineNum NO-LOCK.
    BUFFER-COPY OrderLine TO bUpdateOline.
    IF bUpdateOline.ExtendedPrice >
      (ttOline.ExtendedPrice * 1.2) THEN DO:
      cMessage = "Line " + STRING(OrderLine.LineNum) +
        ": Can't increase price by more than 20%.".
      UNDO, LEAVE.
    END.    ...
  END. /* DO FOR EACH ttOline */

Este podría no ser el comportamiento que desea. Por un lado, es posible que desee que todas las líneas de orden se confirmen juntas o que se deshagan si alguna falla. En otro caso, es posible que desee procesar cada OrderLine como una transacción separada, pero continúe si una de ellas falla. Mira ambos casos.
En el primer caso, desea que todas las actualizaciones de OrderLine tengan éxito o fracasen juntas. Si cualquiera falla su validación, todos se retrotraen.

Para confirmar todos los registros de OrderLine juntos o deshacerlos si falla alguna actualización de un registro:

1. Defina que el alcance de la transacción sea mayor que una única iteración del bloque FOR EACH colocando un nuevo bloque DO TRANSACTION a su alrededor. Luego, agregue una etiqueta para ese nuevo bloque para identificar cuánto deshacer en su declaración UNDO:

  OlineBlock:
  DO TRANSACTION:
    FOR EACH ttOline WHERE ttOline.TransType = "":
2. Change the UNDO statement to undo the entire larger transaction and to leave that outer block as well:
 UNDO OlineBlock, LEAVE OlineBlock.
Remember that the default is to undo and leave the innermost block with the error property, the FOR EACH block.
3. Add another END statement to match the new DO TRANSACTION statement that begins the new block:
      END. /* ELSE DO If we updated the OrderLine */
    END./* DO FOR EACH ttOline */
  END. /* new DO TRANSACTION block */
Note that a block label, such as OlineBlock:, does not require a matching END statement. It is simply an identifier for a place in the code and does not actually start a block of its own.
4. Make a change to the code that restores the original values to the temp-table if there's an error. Because the error might not be on the line that's current when you leave the block, you need to re-read all the OrderLines for the Order and buffer-copy their values back into the update copies of each of the temp-table records, in a FOR EACH loop:
  IF cMessage NE "" THEN DO:
    FOR EACH OrderLine
      WHERE OrderLine.OrderNum = bUpdateOline.OrderNum NO-LOCK:
      FIND bUpdateOline WHERE OrderLine.LineNum = bUpdateOline.LineNum
        AND bUpdateOline.TransType = "U".
      BUFFER-COPY OrderLine TO bUpdateOline.
    END.
    RETURN cMessage.
  END.
Now if you make changes to three OrderLines, and the second of the three is invalid, then all three changes are rolled back because they're all part of one large transaction. You see this reflected in your window.



NUM-ENTRIES function
Devuelve el número de elementos en una lista de cadenas de caracteres como un valor INTEGER
list
Una expresión de caracteres que contiene una lista de cadenas de caracteres separadas con un delimitador de caracteres. La lista puede ser una variable de tipo CHARACTER o LONGCHAR. NUM-ENTRIES devuelve el número de elementos en la lista. Específicamente, NUM-ENTRIES devuelve el número de delimitadores más 1, y devuelve 0 si la lista es igual a la cadena vacía ("").
character
Un delimitador que definas para la lista. El valor predeterminado es una coma (,). Esto permite que las funciones operen en listas separadas por comas. Si utiliza un carácter alfabético, este delimitador distingue entre mayúsculas y minúsculas.
DEFINE VARIABLE ix      AS INTEGER   NO-UNDO.
DEFINE VARIABLE regions AS CHARACTER NO-UNDO
  INITIAL "Northeast,Southest,Midwest,Northwest,Southwest".

REPEAT ix = 1 TO NUM-ENTRIES(regions):
  DISPLAY ENTRY(ix, regions) FORMAT "x(12)".
END.



Declaración de  RETURN
Abandona el procedimiento local o remoto o el bloque de funciones definidas por el usuario, el bloque desencadenante, el bloque desencadenante de la base de datos, el bloque de métodos de una clase, el bloque constructor de clases o el bloque de acceso a la propiedad, y regresa al procedimiento de llamada, función definida por el usuario, Método, constructor, o propiedad accesor. Si no hay una persona que llama, RETURN regresa al Editor de procedimientos u otra herramienta ADE o Progress Developer Studio para OpenEdge que invocó el procedimiento, la función definida por el usuario, el bloque desencadenante, el activador de la base de datos, el método basado en clases, el constructor o el acceso a la propiedad.



DISPLAY statement

Mueve los datos a un búfer de pantalla y muestra los datos en la pantalla u otro destino de salida. El AVM utiliza marcos para mostrar datos. Un cuadro describe cómo se organizan los datos constantes y variables para la visualización y la entrada de datos. Puede dejar que ABL construya marcos predeterminados o puede describir explícitamente los marcos y sus características.


    DISPLAY  cvarcuentas + " => " + ccodpres WITH FRAME a COLUMN 1 ROW 1 1 COLUMN.




&SCOPED-DEFINE preprocessor directive
Define una constante de tiempo de compilación (nombre del preprocesador) no global.

&SCOPED-DEFINE preprocessor-name definition


preprocessor-name
El nombre del preprocesador (constante de tiempo de compilación) que proporciona. Las palabras clave reservadas de ABL están permitidas, pero no pueden usarse en expresiones de preprocesador.
definition
Una cadena de caracteres (o referencias de preprocesador que evalúan a una cadena de caracteres) cuyo contenido el preprocesador sustituye al nombre de preprocesador durante la compilación. Si la definición es más larga que en línea, una tilde (~) al final de una línea indica la continuación a la siguiente línea.

&SCOPED-DEFINE tblCta {&tbCuenta}

Notas
* Debe colocar la directiva & SCOPED-DEFINE al principio de una línea, precedida solo por espacios en blanco, caracteres de tabulación o comentarios (/ * comentario * /). El preprocesador recorta todos los espacios iniciales y finales de la definición.
* La sintaxis de las directivas & GLOBAL-DEFINE y & SCOPED-DEFINE son idénticas, pero estas directivas se utilizan de manera diferente.

DEFINE BUFFER statement

DEFINE BUFFER bffAfc FOR {&tblCta}.

ABL le proporciona un búfer predeterminado para cada tabla o tabla temporal que use en un procedimiento o clase. ABL usa ese búfer para almacenar un registro a la vez de la tabla, ya que los registros se necesitan durante el procedimiento o la clase. Si necesita más de un registro o búfer a la vez para una tabla, puede usar esta declaración para definir búferes alternativos que se crean en el momento de la compilación para usar en uno o más procedimientos, o dentro de una sola clase o jerarquía de clases.






DISPLAY statement

Mueve los datos a un búfer de pantalla y muestra los datos en la pantalla u otro destino de salida. El AVM utiliza marcos para mostrar datos. Un cuadro describe cómo se organizan los datos constantes y variables para la visualización y la entrada de datos. Puede dejar que ABL construya marcos predeterminados o puede describir explícitamente los marcos y sus características.

DEFINE VARIABLE ccodpres AS CHARACTER.
DEFINE VARIABLE lipoa AS INTEGER.
DEFINE VARIABLE cpartida AS CHARACTER.
DEFINE VARIABLE cvarcuentas AS CHARACTER.
DEFINE VARIABLE cMtP AS CHARACTER.
    cvarcuentas = '19.1000.1200.122.1221.20.05.01.1.1.12590'.
    ccodpres    = STRING(ENTRY(1,cvarcuentas,"."),"99") + "." + STRING(ENTRY(6,cvarcuentas,"."),"99") + "." + STRING(ENTRY(7,cvarcuentas,"."),"99") + "." + STRING(ENTRY(8,cvarcuentas,"."),"99") + "." + STRING(ENTRY(9,cvarcuentas,"."),"99") + "." + STRING(ENTRY(10,cvarcuentas,"."),"99").
    lipoa       = INT(ENTRY(11,cvarcuentas,".")).
    cpartida    = ENTRY(5,cvarcuentas,".").
    DISPLAY  cvarcuentas + " => " + ccodpres WITH FRAME a COLUMN 1 ROW 1 1 COLUMN.




&SCOPED-DEFINE preprocessor directive
Define una constante de tiempo de compilación (nombre del preprocesador) no global.

&SCOPED-DEFINE preprocessor-name definition


preprocessor-name
El nombre del preprocesador (constante de tiempo de compilación) que proporciona. Las palabras clave reservadas de ABL están permitidas, pero no pueden usarse en expresiones de preprocesador.
definition
Una cadena de caracteres (o referencias de preprocesador que evalúan a una cadena de caracteres) cuyo contenido el preprocesador sustituye al nombre de preprocesador durante la compilación. Si la definición es más larga que en línea, una tilde (~) al final de una línea indica la continuación a la siguiente línea.

&SCOPED-DEFINE tblCta {&tbCuenta}

Notas
* Debe colocar la directiva & SCOPED-DEFINE al principio de una línea, precedida solo por espacios en blanco, caracteres de tabulación o comentarios (/ * comentario * /). El preprocesador recorta todos los espacios iniciales y finales de la definición.
* La sintaxis de las directivas & GLOBAL-DEFINE y & SCOPED-DEFINE son idénticas, pero estas directivas se utilizan de manera diferente.

DEFINE BUFFER statement

DEFINE BUFFER bffAfc FOR {&tblCta}.

ABL le proporciona un búfer predeterminado para cada tabla o tabla temporal que use en un procedimiento o clase. ABL usa ese búfer para almacenar un registro a la vez de la tabla, ya que los registros se necesitan durante el procedimiento o la clase. Si necesita más de un registro o búfer a la vez para una tabla, puede usar esta declaración para definir búferes alternativos que se crean en el momento de la compilación para usar en uno o más procedimientos, o dentro de una sola clase o jerarquía de clases.





EMPTY-TEMP-TABLE( ) method

Elimina todos los registros de una tabla temporal asociada con un objeto de búfer o de una tabla temporal identificada directamente por un controlador de objeto de tabla temporal.
Cuando se vacía una tabla temporal que se define como UNDO en una transacción, el AVM borra los registros individualmente. Esto es menos eficiente que vaciar la tabla temporal fuera de la transacción, donde el AVM borra todos los registros en la tabla temporal como una unidad.
Tipo de devolución: LÓGICA

EMPTY TEMP-TABLE ttCta.





BUFFER-FIELD( ) method

Devuelve un identificador a un campo particular en el búfer.
Return type: HANDLE
Applies to: Buffer object handle
Syntax

BUFFER-FIELD ( field-number | field-name )

field-number
Una expresión entera que representa el número de secuencia del campo en el búfer.
field-name
A CHARACTER string Expresión que representa el nombre del campo en el búfer.

miércoles, 30 de enero de 2019

Normas de denominación para pruebas unitarias.


El nombramiento básico de una prueba consta de tres partes principales:  [UnitOfWork_StateUnderTest_ExpectedBehavior] Una unidad de trabajo es un caso de uso en el sistema que comienza con un método público y termina con uno de los tres tipos de resultados: un valor / excepción de retorno, un cambio de estado en el sistema que cambia su comportamiento o una llamada a un Tercero (cuando usamos mocks). por lo tanto, una unidad de trabajo puede ser pequeña como un método, o tan grande como una clase, o incluso múltiples clases. siempre y cuando todo se ejecute en la memoria, y está totalmente bajo nuestro control.

Examples:
Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()
Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()
Public void Sum_simpleValues_Calculated ()


Razones:

El nombre de la prueba debe expresar un requisito específico

El nombre de su prueba de unidad debe expresar un requisito específico. Este requisito debe derivarse de algún modo de un requisito comercial o de un requisito técnico. En cualquier caso, ese requisito se ha dividido en partes suficientemente pequeñas, cada una de las cuales representa un caso de prueba. Si su prueba no representa un requisito, ¿por qué la escribe? ¿Por qué es ese código incluso allí?

Además, los desarrolladores que están en un rol están felices de dar nombres sin sentido o numerados a su prueba para que puedan continuar con lo que están haciendo. Esto conduce a una pendiente estrecha donde rápidamente nadie tiene el tiempo o la energía para arreglar los nombres de las pruebas. Además, la mayoría de los desarrolladores no se preocupan demasiado por escribir buenos mensajes de afirmación en sus pruebas. Un buen mensaje de afirmación (que aparece si la prueba falla) es para comprender qué salió mal. Asumir que los mensajes de aseveración son buenos es uno de los lugares clave donde la mayoría de los desarrolladores de pruebas unitarias se quedan cortos, lo único que queda para salvarnos es el nombre de la prueba. Si tanto el nombre de la prueba como los mensajes de error no son lo suficientemente expresivos, el desarrollador de mantenimiento deficiente (a menudo el mismo que desarrolló las pruebas) se pregunta qué pensaba este bromista. Mirando un código base de años con pruebas unitarias.
El nombre de la prueba debe incluir la entrada o estado esperado y el resultado esperado para esa entrada o estado

Para expresar claramente el requisito específico, debe pensar en dos cosas que debe expresar: los valores de entrada / estado actual durante el cual se realiza la prueba y el resultado esperado de ese estado.

Ejemplo:
Dado este método:Example:
Public int Sum(params int[] values)
You have a requirement that numbers larger than 1000 that are passed in should not be considered for calculation (that is a number bigger than 1000 is equal to zero).
What about this name: Sum_NumberBiggerThan1000
That is only half way there. As a reader of the test I can only assume that some input in your test is bigger than 1000, but I do not understand what the requirement being tested is.
How about this name: Sum_NumberIsIgnored
Still not good enough. While it does tell me the expected result, it does not tell me under which circumstances it needs to be ignored. I would have to go into the test code and read through it to find out what the expected input is.
How about this name: Sum_NumberIgnoredIfBiggerThan1000
That s much better. I can tell just by looking at the test name what It means if the test fails. I don t need to look at the code, and I can tell exactly what requirement this test tries to solve.
Test name should be presented as a statement or fact of life that expresses workflows and outputs
Unit tests are just as much about documentation as they are about testing functionality. You should always assume that someone else is going to read your tests in a year, and that they should not have a hard time understanding your intent.
Test names which are written as short declarative statements are much more expressive that names which are machine readable that is they only make sense if you have an understanding of a hidden code language to dissect their meaning.
People might first complain that the name of the test method appears way too long for them, but in the end it s more about readability. Longer test names do not imply longer or less optimized code, and even if they did, we are not looking to optimize test code performance. If anything, test code should always be optimized for readability.
Here s an example of a bad an d good test name
Public void SumNegativeNumber2()
And here s a better way to express your intent
Public void Sum_ExceptionThrownOnNegativeNumberAs2ndParam ()
Test Name should only begin with Test if it is required by the testing framework or if it eases development and maintenance of the unit tests in some way.
Since most tests today reside in a specific class or module that is logically defined as a test container (fixture), there are only a handful of reasons why you would want to prefix you test methods with the word Test :
- Your unit testing framework requires this
- You have coding standards in place and they include this
- You want to make it easier to navigate to the methods using Intellisense or some other search mechanism.
Test name should include name of tested method or class
You usually have at least a number of tests for each method you are testing, and you are usually testing a number of methods in one test fixture (since you usually have a test fixture per class tested). This leads to the requirement that your test should also reflect the name of the method begin tested, not only the requirements from it.
For example:
   [MethodName_StateUnderTest_ExpectedBehavior]
Public void Sum_NegativeNumberAs1stParam_ExceptionThrown()
Public void Sum_NegativeNumberAs2ndParam_ExceptionThrown ()
Public void Sum_simpleValues_Calculated ()
Public void Parse_OnEmptyString_ExceptionThrown()
Public void Parse_SingleToken_ReturnsEqualToeknValue ()
Naming Variables in a test:
Variable names should express the expected input and state
It s easy to name variables going into a method with generic names, but with unit tests you have to be twice as careful to name them as what they represent, i.e. BAD_DATA or EMPTY_ARRAY or NON_INITIALIZED_PERSON
You do not need to name them with a CONST casing , but the name does have to represent the intent of the test author.
A good way to check if your names are good enough is to look at the ASSERT at the end of the test method. If the ASSERT line is expressing what your requirement is, or comes close, you re probably there.
For example:
Assert.AreEqual(-1, val)
Vs.
Assert.AreEqual(BAD_INITIALIZATION_CODE, ReturnCode, Method shold have returned a bad initialization code )

Nuget visual studio

NuGet es una extensión de Visual Studio que hace más fácil agregar, eliminar y actualizar referencias a librerías y herramientas en proyectos de Visual Studio que utilizan .NET Framework. ... Todo lo necesario para instalar una biblioteca o una herramienta se incluye en un paquete (un archivo. Nupkg).