---
# System prepended metadata

title: 'Assignment #2'

---

![](https://i.imgur.com/r2Upi0M.png)

## Verificação e Validação de Software

### Professor: 
José Campos

### Alunos:
João Lopes      nº55812
Filipe Martins  nº55814

# Assignment #2

Este assignment consiste na realização de testes unitarios, sendo estes testes do tipo *Black-Box Testing* e através do metodo Category-Partition.Para tal tivemos de identificar 5 funções do projeto Jpass para testar, tendo estas de pertencer ao pacote assignado **jpass.util**.

O Category-Partition proporciona-nos uma forma sistemática de desenvolver
testes derivados, com base nas características dos parametros das funções
parâmetros. Através disto conseguimos reduzir o número de testes a um
número prático.
Para a realização dos testes unitários utilizamos a ferramente JUnit, que é uma das ferramentas mais utilizadas na criação de testes unitários para Java.

Neste assignment consta uma breve explicação da função a ser testada, como foi utilizada a category-partition e quais os testes a realizar para a mesma, e por fim uma explicação dos testes desenvolvidos e também os resultados obtidos.

## Função - 1

Esta função tem como propósito remover todos os caracteres que não são imprimíveis, para tal é utilizado um *loop* pelos caracteres da `String` fornecida como parâmetro e é verificado se cada caracter é ou não imprimível, utilizando o seu valor hexadecimal, caso o caracter não seja imprimível é substituído por o caracter `'?'`.

```
 public static String stripNonValidXMLCharacters(final String in) {
        if (in == null || in.isEmpty()) {
            return in;
        }
        StringBuilder out = new StringBuilder();
        char current;
        for (int i = 0; i < in.length(); i++) {
            current = in.charAt(i);
            if ((current == 0x9) || (current == 0xA) || (current == 0xD)
                    || ((current >= 0x20) && (current <= 0xD7FF))
                    || ((current >= 0xE000) && (current <= 0xFFFD))) {
                out.append(current);
            } else {
                out.append('?');
            }
        }
        return out.toString();
    }
```
**Category-Partition**

Em termos dos parâmetros existentes nesta função, só temos um, que é uma `String`, este parâmetro não pode ser *null* nem vazio, de resto pode ter qualquer valor valido para uma string, seja ele imprimível ou não.
Desta forma obtemos os testes possíveis a desenvolver:

* `String` com o valor *null*.
* `String` com o valor vazio.
* `String` com caracteres não imprimíveis.
* `String` sem caracteres não imprimíveis.

**Testes unitários**

 No primeiro teste o objetivo era verificar se a função conseguia ou não lidar com o parâmetro *null*, após a sua realização concluímos que a função lida bem com este caso, sendo retornado o valor fornecido, neste caso *null*.
 
 Seguiu-se o teste onde pretendemos verificar se a função lidava bem com um parâmetro vazio, tal como no teste prévio. Também concluímos que a função lida bem com strings vazias, retornando a mesma.
 
O terceiro teste teve como objetivo verificar se a função realmente substitui os caracteres não imprimíveis, para tal utilizamos o caracter � e mais quatro caracteres que eram imprimíveis.
No final verificamos que a string retornada tinha o caracter substituído, tendo, portanto, funcionado como previsto.

Por fim foi testada uma string sem caracteres não imprimíveis, onde era previsto não ser feita qualquer alteração a string fornecida.
Após execução do teste conseguimos comprovar o que tinha sido previsto, ou seja, nenhum dos caracteres presentes na string foi alterado.

 
## Função - 2

A função `formatIsoDateTime` tem como objetivo receber uma data em formato `String` e retornar a mesma transformada no formato pretendido. Para tal recebe 2 argumentos, uma data em formato `String` e `DateTimeFormatter` com o formato que deve ser aplicado à data. 
Em primeiro lugar a função tenta transformar a data passada como argumento para o formato desejado, caso não seja possível, a função tenta criar uma variável `Date` com a string passada como argumento, caso também não seja possível a função devolve uma a primeira data conhecido ’01.01.1970 ’no formata desejado.


```
public static String formatIsoDateTime(String dateString, DateTimeFormatter formatter) {
        LocalDateTime dateTime;
        try {
            dateTime = LocalDateTime.parse(dateString, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
        } catch (DateTimeParseException | NullPointerException e) {
            try {
                // fallback to epoch timestamp
                Date date = new Date(Long.parseLong(dateString));
                dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
            } catch (NumberFormatException | DateTimeParseException | NullPointerException ex) {
          
                dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault());
            }
        }
        return formatter.format(dateTime.truncatedTo(ChronoUnit.SECONDS));
    }
```

**Category-Partition**

Em relação aos parâmetros existentes nesta função, temos dois, uma data do tipo `String`, e um `DateTimeFormatter`, que corresponde a formatação desejada para a data fornecida. Em termos de características/restrições, ambos os parâmetros só não podiam ser nulos. 
De forma a testar todas as formas possíveis foram criadas as seguintes categorias. Um `DateTimeFormatter`: *null*, vazio, correto ou   incorreto sendo que para cada uma destas hipóteses será utilizada uma string com uma data correta, incorreta, vazia ou *null*.
Assim obtemos os possíveis testes a desenvolver:



* `DateTimeFormatter` vazio.
* `DateTimeFormatter` `null` com uma data correcta.
* `DateTimeFormatter` `null` com uma data incorreta.
* `DateTimeFormatter` `null` com uma data vazia.
* `DateTimeFormatter` `null` com uma data `null`.
* `DateTimeFormatter` incorreto com uma data correcta.
* `DateTimeFormatter` incorreto com uma data incorreta.
* `DateTimeFormatter` incorreto com uma data vazia.
* `DateTimeFormatter` incorreto com uma data `null`.
* `DateTimeFormatter` correto com uma data correcta.
* `DateTimeFormatter` correto com uma data incorreta.
* `DateTimeFormatter` correto com uma data vazia.
* `DateTimeFormatter` correto com uma data `null`.

**Testes Unitários**

Para começar foi feito um teste com o `DateTimeFormatter` a vazio, a função devolve uma string vazia, apesar de não serem levantadas exceções, esta situação sugere que a função deve ser revista pois esta não aparenta ser o comportamento desejado.

Para a segunda bateria de testes no qual o `DateTimeFormatter` esta fixo com o valor `null` sendo o único ponto de variação na data. Todos os testes deram conforme esperado, o que sugere que os métodos foram bem implementados.

Para a terceira bateria de testes o parâmetro `DateTimeFormatter` foi testado com o valor da incorreto e com a data a `null` Todos os testes deram positivo.

Por fim bastou testar o `DateTimeFormatter` correto fixo com variação na data. Todos os testes deram positivo.

## Função - 3

O Propósito da função `createFormatter` é de através de um padrão de datas do tipo `String` recebido como parâmetro, ex. (01-01-2010), caso este seja valido, transformá-lo num objeto do tipo `DateTimeFormatter` de modo a formatar datas do tipo `DateTime`.
A função recebe o padrão desejado como string e tenta criar um objeto do tipo `DateTimeFormatter` utilizando o método `DateTimeFormatter.ofPattern(String pattern)`, caso o padrão seja valido o objeto será criado e retornado pela função, caso seja invalido o método tentará apanhar uma exceção do tipo `IllegalArgumentException`, que indica que o padrão não é um padrão valido para formatar datas, ou uma exceção do tipo `NullPointerException` caso o padrão esteja a *null*. Nestes casos o método retorna um `DateTimeFormatter` pré-definido utilizando o padrão `ISO_DATE`.


```
public static DateTimeFormatter createFormatter(String format){
        DateTimeFormatter formatter;
        try {
            formatter = DateTimeFormatter.ofPattern(format);
        } catch (IllegalArgumentException | NullPointerException e) {
            LOG.log(Level.WARNING, String.format("Could not parse date format [%s] due to [%s]", format, e.getMessage()));
            formatter = DateTimeFormatter.ISO_DATE;
        }
        return formatter;
    }
```

**Category-Partition**

De modo a testarmos o método especificado dividimos os testes em categorias, e desta forma cobrindo todos os possíveis resultados da função. Para tal inicialmente analisamos o tipo de parâmetro necessário e qual o seria o resultado esperado, assim sendo começamos por separar em 2 partes, parâmetro com valor e sem valor.

Começando pela primeira parte, verificamos que caso o padrão fornecido fosse valido deveria ser retornado o `DateTimeFormatter` específico, mas caso o mesmo seja invalido deveria ser retornado um `DateTimeFormatter` definido internamente. Assim ficamos com as duas primeiras categorias:

* Parametro `format` com um valor valido. Exemplo: `"21.12.2021"`
* Parametro `format` com um valor invalido. Exemplo: `"21.12.202"`

Passando para a segunda parte, verificamos que tanto podemos passar um padrão a `null` como um padrão vazio. Em ambos os casos deve ser retornado o `DateTimeFormatter` definido internamente. Desta forma obtemos as restantes categorias:

* Parametro `format` com o valor null. Exemplo: `null`
* Parametro `format` com o valor vazio. Exemplo: `""`



**Testes Unitários**

Tendo obtido quais os testes necessários a realizar, foram então criados e analisados, de modo a verificar se a função a ser avaliada se comportava como planeado.

Começando pelo teste para quando o padrão tem o valor *null*, o mesmo teve como objetivo verificar se a função conseguia lidar com o valor *null*.
Neste teste o valor esperado seria um `DateTimeFormatter` pré-definido internamente, algo que se sucedeu. 
Desta forma concluímos que esta função consegue lidar bem com o valor *null*, e não emite exceções relacionadas com o mesmo.

Passando ao teste referente ao padrão ter um valor vazio, tal como no teste anterior, a função deveria retornar o `DateTimeFormatter` pré-definido internamente. Neste teste conseguimos perceber que o mesmo não ocorre, o que é retornado é um `DateTimeFormatter` vazio, ou seja, a função não verifica se o input é uma string vazia e deixa que esta seja utilizada para criar o objeto do tipo `DateTimeFormatter`. 
Este problema pode levar a diversos erros, visto que esta função é utilizada para criar o formatador de datas, e desta forma várias datas irão ser apagadas com este formatador.

De seguida temos o teste para quando o padrão tem um valor invalido, neste caso, como o padrão fornecido não existe, e não é possível a criação do objeto `DateTimeFormatter`, deveria ser retornado o `DateTimeFormatter` pré-definido. Neste teste concluímos que o mesmo se sucede, ou seja, não é criado um formatador invalido, nem nos é emitida uma exceção, tal como seria esperado o `DateTimeFormatter` pré-definido é retornado.

Por fim temos o teste referente ao padrão ter um valor valido, este é o único caso onde deveria ser retornado o `DateTimeFormatter` com o padrão fornecido.
Após analise do teste verificamos que este é realmente o seu comportamento, retornando o `DateTimeFormatter` correto.




## Função - 4

Esta função tem como objetivo cortar uma `String` com mais de x caracteres e retornar uma `String`. A função recebe uma string como argumento e um número que ira servir para limite de carateres, a função ira depois verificar se a string tem ou não um número de caracteres superior ao que foi passado como parâmetro. Caso seja superior a mesma ira ser cortada e todos os caracteres depois do limite irão serão substituídos por '...' caso contrário é devolvida a string por inteiro.
  
```
    public static String stripString(String text) {
        return stripString(text, 80);
    }

    public static String stripString(String text, int length) {
        String result = text;
        if (text != null && text.length() > length) {
            result = text.substring(0, length) + "...";
        }
        return result;
    }
```

**Category-Partition**

Visto existirem dois parâmetros, a partição dos parâmetros tem de ser feita em conjunto de forma a testar todas as hipóteses possíveis para os parâmetros. O limite que deve ser estabelecido para cortar a string, deve ser testado com um número positivo, negativo e igual a 0 e a string com um número de caracteres, caso seja possível, superior, inferior e igual ao limite estabelecido.

**Limite igual a 0:**

* Limite igual a 0 e uma `String` com um número de caracteres superior a 0.
* Limite igual a 0 e uma `String` com um número de caracteres igual a 0.

Existe a hipótese de o limite ser 0, neste caso existe a possibilidade da `String` passada como argumento ter um número de carateres superior ou igual a 0.

* Limite igual a 0 e uma `String` com um número de caracteres inferior a 0.

Este cenário é impossível pois não é possível criar uma string com um número de caracteres inferior a 0.

**Limite superior a 0 (limite de 10):**

* Limite igual a 10 e uma `String` com um número de caracteres superior a 10.
* Limite igual a 10 e uma `String` com um número de caracteres inferior a 10.
* Limite igual a 10 e uma `String` com um número de caracteres igual a 10.


**Limite inferior a 0 (limite de -2):**

* Limite inferior a -2 e uma `String` com um número de caracteres igual a 10. 
Para este cenário basta testar para um caso. O caso em que o limite ´inferior a 0, eliminado assim a necessidade de ter que realizar outros testes para o tamanho da `String`. 

**Testes Unitários**

Para o primeiro caso da Category-Cartition, os testes para esta categoria passam por realizar 2 métodos com o limite de caracteres fixo no número 0 e em que a o único ponto de variância é o tamanho da string. Ambos os testes deram positivo, pelo que o resultado esperado é cumprido, validando assim esta categoria de testes.

O segundo caso da Category-Cartition, passa por realizar 3 métodos com o limite de caracteres igual a 10 e com uma string superior, inferior ou igual ao limite. Todos os testes deram positivo, pelo que o resultado esperado é cumprido, validando assim esta categoria de testes.

Para o caso em que o limite é negativo o tamanho da string não tem nenhuma importância, pois o *length* com um número negativo iria levantar uma exceção. Este teste levanta uma exceção pelo que deve ser prudente verificar e rever a função de forma a evitar problemas no futuro.



## Função - 5

A ultima função escolhida para realizar os testes é a função `setClipboardContent(String str)`, esta função tem como objetivo recebe uma string  definir a mesma no System ClipBoard.

```
public static void setClipboardContent(String str) throws Exception {
        if (str == null || str.isEmpty()) {
            clearClipboardContent();
            return;
        }
        try {
            StringSelection selection = new StringSelection(str);
            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
        } catch (Throwable throwable) {
            throw new Exception("Cannot set clipboard content.");
        }
    }
```

**Category-Partition**

De forma a conseguirmos testar o método na sua completude temos primeiro de analisar o parâmetro da mesma perceber quais os possíveis parâmetros. A função em questão recebe apenas uma `String` como parâmetro, o que torna os testes a realizar bastante fáceis pois só temos 3 casos possíveis.

* Parametro `String` com um valor valido. Exemplo: `"Novo conteúdo!!""`
* Parametro `String` com um valor empty. Exemplo: `""`
* Parametro `String` com um valor null. Exemplo: `null`

**Testes Unitários**

Tendo obtido quais os testes necessários a realizar, foram então criados e analisados, de modo a verificar se a função a ser avaliada se comportava como planeado.

Foram realizados 3 métodos para cobrir todas as hipóteses possíveis.
O primeiro teste foi feito com uma string válida de forma a testar se quando o parâmetro passado é valido existe algum problema. O teste foi bem-sucedido.
O segundo e terceiro testes apontam para testar se a função esta preparada para receber algo diferente de uma string válida, foram realizados testes para uma string empty e um objeto null. Ambos os testes passaram, pois, a função trato o argumento como era suposto.
Em suma, esta função passou em todos os testes que pensamos que façam sentido realizar.

