Test técnico Android — Qualified.io
Objetivo: Crear una aplicación móvil Android nativa con arquitectura limpia, validaciones dinámicas y pruebas unitarias.
- Simular la respuesta de una API desde un archivo JSON en
/assets/. - Renderizar dinámicamente un formulario en Compose con campos definidos en el JSON.
- Aplicar validaciones de
maxlengthyregex. - Mostrar solo campos visibles, ordenados por
order. - Implementar botón de validación al final del formulario.
- Utilizar MVVM + Clean Architecture.
- Aplicar buenas prácticas de diseño y pruebas unitarias.
Se aplicó una arquitectura modular y escalable con separación de responsabilidades en 3 capas:
+-------------------+ +---------------------+ +------------------+
| presentation | <-----> | domain | <-----> | data |
| (UI, ViewModel) | | (use cases, models) | | (sources, models)|
+-------------------+ +---------------------+ +------------------+
- presentation: Jetpack Compose UI + ViewModel que expone estado observable.
- domain: Entidades puras (
Field) y casos de uso (GetFieldsUseCase). - data: Fuente de datos simulada desde
assets/, modelosDTO(FieldDto) y mapeo a dominio.
| Herramienta | Uso |
|---|---|
| Kotlin | Lenguaje base |
| Jetpack Compose | UI moderna declarativa |
| Koin | Inyección de dependencias |
| Coroutines + Flows | Programación asíncrona y reactiva |
| Gson | Parsear JSON desde assets |
| JUnit | Pruebas unitarias |
| kotlinx-coroutines-test | Test de flujos y ViewModel |
- El archivo
sample.jsonse carga como si viniera de una API real. - Se usó
Gsonpara parsear el JSON a unMap<String, FieldDto>. - Se filtraron campos
visible == truey se ordenaron pororder.
Se creó una función toDomain() que convierte cada FieldDto a un Field, usando los parámetros necesarios para la UI:
key,label,type,maxlength,regex,values
- Renderizado con
TextField,Dropdown, etc. - Validación en tiempo real por campo.
- Botón de validación general.
AppModule.kt provee:
FormRepositoryImplGetFieldsUseCaseFormViewModel
GetFieldsUseCaseTest: campos visibles y ordenados.FormViewModelTest:StateFlowinicializado.ValidatorTest: pruebas puras de lógica de validación.
fun validate(field: Field, value: String): String? {
if (field.maxLength != null && value.length > field.maxLength)
return "Máximo ${field.maxLength} caracteres"
if (!field.regex.isNullOrBlank() && !Regex(field.regex).matches(value))
return "Formato inválido"
return null
}- Respeta principios SOLID y buenas prácticas modernas.
- Modular, fácil de testear, extender y mantener.
- Flujo realista simulando respuesta de API.
- Jetpack Compose + Koin + Coroutines: stack moderno y recomendado.
- App funcional, escalable y profesional.
- Validaciones dinámicas.
- UI declarativa.
- Código bien estructurado y probado.