Функция Validate проверяет, являются ли значения одного столбца или всей записи допустимыми для источника данных.
Описание
Вы можете настроить мгновенную проверку пользовательских изменений перед их отправкой, чтобы оптимизировать работу пользователей с данными.
Источники данных могут содержать информацию о том, какие значения в записях считаются допустимыми. Эти сведения могут включать различные ограничения, например:
- требуется ли значение в определенном столбце;
- максимальная допустимая длина для текстовой строки;
- максимальное и минимальное значения для числа;
- нижняя и верхняя границы диапазона для даты.
Функция Validate использует эту информацию, чтобы определить, является ли значение допустимым, и в противном случае возвращает соответствующее сообщение об ошибке. Для просмотра информации, которую использует функция Validate, можно воспользоваться функцией DataSourceInfo.
Источники данных различаются по объему доступных сведений о проверке и могут вообще не содержать их. Функция Validate способна проверять значения только на основе этой информации. Даже если функция Validate не выявила проблем, попытка применить изменения в данных все равно может завершиться ошибкой. Получить информацию о ней можно с помощью функции Errors.
VERIFICATION and VALIDATION (Верификация и Валидация) in Software Testing | Отличия | Примеры
Если функция Validate обнаруживает проблему, она возвращает сообщение об ошибке, которое можно продемонстрировать пользователю приложения. Если все значения допустимы, Validate возвращает пустое значение. При работе с коллекцией, в которой нет информации о проверке, значения всегда считаются действительными.
Синтаксис
Validate( DataSource, Column, Value )
- DataSource — обязательный аргумент. Источник данных, с которым необходимо сверить значение.
- Column — обязательный аргумент. Столбец, который необходимо проверить.
- Value — обязательный аргумент. Значение в выбранном столбце, которое необходимо проверить.
Validate( DataSource, OriginalRecord, Updates )
- DataSource — обязательный аргумент. Источник данных, с которым необходимо сверить значение.
- OriginalRecord — обязательный аргумент. Запись, обновления которой необходимо проверить.
- Updates — обязательный аргумент. Изменения, которые требуется применить к исходной записи.
Примеры
В этих примерах значения в столбце Percentage (Процент) источника данных Scores (Показатели) должны находиться в диапазоне от 0 до 100 включительно. Если данные проходят проверку, функция возвращает пустое значение. В противном случае она возвращает сообщение об ошибке.
Проверка одного столбца
Validate( Scores, Percentage, 10 ) | Проверяет, является ли 10 допустимым значением для столбца Percentage в источнике данных Scores. | пусто |
Validate( Scores, Percentage, 120 ) | Проверяет, является ли 120 допустимым значением для столбца Percentage в источнике данных Scores. | «Значения должны быть в диапазоне от 0 до 100». |
Проверка всей записи
Validate( Scores, EditRecord, Gallery.Updates ) | Проверяет, допустимы ли значения во всех столбцах для источника данных Scores. В этом примере значение в столбце Percentage равно 10. | пусто |
Validate( Scores, EditRecord, Gallery.Updates ) | Проверяет, допустимы ли значения во всех столбцах для источника данных Scores. В этом примере значение в столбце Percentage равно 120. | «Значения должны быть в диапазоне от 0 до 100». |
Источник: learn.microsoft.com
Verification and Validation простыми словами
html валидность кода, что такое, зачем и как проверять
Верстка
В данном уроке будем разбираться, что такое валидность html, зачем нужна валидация кода, и как ее проверить онлайн и при помощи плагинов.
Что такое html валидность
Валидность HTML-верстки — это её соответствие стандартам организации W3C. Отсутствие ошибок в вёрстке документа — один из основных показателей её качества.
При этом, соблюдение стандартов не обязательно для того, чтобы сайт отображался в браузерах.
Зачем нужна валидация кода
Правильный, валидный html-код — это код, написанный по спецификации W3C, в которой собраны стандарты и рекомендации по удобству и универсальности Всемирной сети. Даже если ваш сайт отлично отображается в браузере, рекомендую проверить его валидность, как минимум потому что поисковые системы лучше относятся к валидным html страницам и лучше понимают их код.
Онлайн проверка валидности html
Для того чтобы быстро, удобно и в автоматическом режиме проверять свой код, существует помощник — валидатор W3C. Он используется повсеместно (хотя есть и другие), так как придуман и написан консорциумом W3C — теми, кто создал и поддерживает стандарт языка.
Как пользоваться валидатором W3C
Идем на страницу валидатора .
По умолчанию, открыта вкладка «Validate by URI» — валидация документа по его url адресу — сюда достаточно ввеcти URL и нажать на кнопку «Check». Также есть еще 2 вкладки: «Validate by File Upload» — сюда с ПК можно загрузить html файл. И в кладка «Validate by Direct Input», куда можно вставить просто код HTML-фрагмента — давайте разберем на ее примере. Закидываем код и нажимаем кнопку «Check».
В результате, если все валидно и хорошо, вы увидите надпись «Document checking completed. No errors or warnings to show.».
В противном случае валидатор выведет ошибки и предупреждения:

Предупреждения — это какие-то незначительные неточности в коде, которые не сломают сайт, но не соответствуют стандартам кода.
Ошибки — более серьёзные проблемы, которые могут повлиять на работу кода в целом. Это могут быть как грубые ошибки — например, неверная вставка тега в тег, неверное закрытие тега и т.д., так и менее значимые — отсутствие атрибута alt, незаполненный тег title.
Рекомендация: просто исправлять всё, что там есть, чтобы осталось лишь заветное зелёное уведомление о том, что всё правильно. Либо как минимум чтобы остались только предупреждения. Правильность кода — залог его корректной и долговечной работы, а также плюс при работе в команде с другими верстальщикамиbackend-разработчиками.
Как ещё можно проверять верстку
Помимо классического валидатора есть ещё один тип инструментов — так называемые хинтеры. Как правило, это плагины для редакторов кода, которые при написании кода автоматически подчеркивают ошибки и указывают, что нужно исправить. Один из таких плагинов — HTMLHint для редактора VS Code.
Хинтер работает по определённым правилам, которые довольно схожи с правилами валидатора. Но в идеале стоит проверять верстку как хинтером, так и валидатором, чтобы точно всё исправить.
Со списком правил хинтера можно ознакомиться по ссылке .
Массовая проверка html валидности страниц сайта
Массово проверить страницы сайта на валидность и прочие технические SEO проблемы, можно при помощи бесплатной программы (есть ограничения): WebSite Auditor . Запускаем ее, создаем проект, вбиваем адрес сайта — далее — далее. Ждем пока завершиться проверка всех страниц. Идем в пункт страницы с ошибками в коде и запускаем проверку валидации. всех страниц сайта.
После чего получаем список страниц, где присутствуют ошибки, с возможностью перейти в валидатор.
Обычно если сайт на CMS то ошибки кроятся в шаблонах и поправив шаблон мы автоматически их закрываем. А иногда потому что что то не заполнили.
Заключение
Правильный HTML-код крайне важен. Стандарты языка придуманы не просто так. Даже если ошибка кажется несущественной, она может повлиять на логическую сторону кода (например, отсутствие alt — описания изображения).
Всегда проверяйте свой код, обращайте внимание на частые ошибки, чтобы в будущем их не совершать.
Источник: web-revenue.ru
Правильная валидация в Android
Эта статья — обзор моей Android-библиотеки валидации, которая позволяет организовать сложную валидацию данных. В первую очередь библиотека рассчитана на проверку пользовательского ввода.
Часто в мобильных приложениях приходится делать различные экраны для ввода пользователем информации. Но так как пользователи не отличаются умом и сообразительностью — приходится проверять, что они там написали: запрещенные символы, максимальная длина, соответствие RegExp и так далее.
Первое, что приходит в голову для решения проблемы — прицепить регулярку прямо на EditText
Например, вот так:
Но а если теперь я хочу проверять поле по двум разным RegExp и выводить разные ошибки?
Ну тогда можно добавить второй слушатель:
Однако, теперь если в поле ввести строку «12345» то ошибки не будет: первый слушатель выставит ошибку на поле, потому что поле содержит цифры, а вот второй слушатель скроет ошибку, потому что по его мнению — поле правильное, не более 10 символов.
И это только одна проблема. Дальше — веселее:
- Как повесить на поле множество правил валидации, чтобы они правильно работали вместе?
- Как добавлять или удалять правила?
- Где хранить эту кучу валидаторов?
- Как проверять любые типы данных, а не только строковые?
- и многое другое.
Решение
Вся валидация должна происходить во ViewModel или Presenter, но не в UI слое. Задача UI — должным образом реагировать на результат проверки.
Не должно быть никаких специальных view-классов с поддержкой валидации. Валидацию можно привязать к любой view
Валидаторы должны поддерживать множество различных правил проверки, чтобы, например, каждое правило выдавало собственную ошибку.
Схематично всё выглядит примерно вот так:
Теперь рассмотрим её подробнее.
Condition — основа всего
В основе всей валидации лежит условие ( Condition ) — простейший интерфейс с одним методом validate .
Как это работает?
На изи! У Condition есть метод validate(data) , который проверит данные и вернёт результат ValidationResult . Внутри ValidationResult будет булевый результат проверки isValid и сообщение об ошибке, которое должно появляться если isValid == false
Сложений и умножение
Condition можно складывать и умножать. Сложение работает как аналог булевого ИЛИ, а умножение как аналог булевого И
ИЛИ
Conditon(true)
Conditon(false)
Conditon(true)
Conditon(false)
И
Conditon(true)
Conditon(false)
Conditon(true)
Conditon(false)
Точно так же склыдываются или умножаются ValidationResult
Validator — проверка по множеству условий
А что если надо проверять значение по множеству условий?
Как это работает?
Validator по-сути является Condition , только более прокаченный.
Внутри Validator находится множуство условий Set . В момент проверки значение проверяется по каждому из условий, формируется набор результатов валидации Set . Затем, этот набор с результатами передается на вход оператору ( Operator ), который и решает, какой будет финальный результат валидации. Вот, Всё.
У валидатора есть свои приколы:
Оператор
Operator — это просто Condition> , то есть тупа проверяет коллекцию результатов валидации. Получается такой аналог логического оператора из начального курса булевой алгебры. По-умолчанию используется оператор-конъюнкция.
Но можно написать свой оператор, который, например, будет выдавать ValidationResult(true) если количество валидных условий достигло порогового значения.
class ThresholdOperator(val validThreshold: Int) : Validator.Operator < override fun validate(value: Collection?): ValidationResult < val validCount = value?.count < it.isValid >?: 0 return if (validCount >= validThreshold) < ValidationResult.valid() >else < ValidationResult.invalid(«Less than $validThreshold valid conditions») >> >
validator.setOperator(ThresholdOperator(validator.getConditionsSet().size / 2))
Нельзя удалять оператор! Validator не может работать без оператора
Наблюдение за изменением оператора
Может быть такое, что необходимо отслеживать изменения оператора. Например, чтобы обновить view.
validator.addOperatorChangedListener < // on operator changed >//Или удаляем слушателя validator.removeOperatorChangedListener(operatorListener)
Набор условий
validator.addCondition(Condition < string ->ValidationResult.obtain(string?.contains(«target») == true, «String must contains target») >)
validator.removeCondition(condition)
Наблюдение за изменением условий
Чтобы следить за списком условий — добавьте слушателя OnConditionsChangedListener , который будет вызываться при любом изменении условий
validator.addConditionsChangedListener < newConditions ->//on new conditions >
Если нужно сделать много преобразований можно использовать changeConditionsSet , чтобы слушатель OnConditionsChangedListener сработал только один раз — после всех преобразований набора условий.
validator.changeConditionsSet
LiveDataValidator — реактивная валидация
Было бы удобно, если бы валидатор самостоятельно проверял данные при каждом их изменении. Так и сделаем! Сейчас модно молодежно использовать LiveData . Так пусть валидатор подпишется на неё и будет проверять каждое значение.
LiveDataValidator работает так же как и обычный Vlidator , однако у него есть свои особенности:
Состояние (state)
Состояние это результат последней проверки. Представляет собой LiveData , поэтому за состоянием валидатора можно удобно следить. LiveDataValidator всегда в актуальном состоянии пока он подписан на источник ( Validator.observe ; Validator.observeForever )
liveDataValidator.state
Активация LiveDataValidator
LiveDataValidator начинает работать только тогда, когда хоть кто-нибудь подписан на него
liveDataValidator.state.observe(viewLifecycleOwner) < validationResult ->//apply validation result > //Или можно вот так, разницы нет liveDataValidator.observe(viewLifecycleOwner) < validationResult ->//apply validation result >
Реакция на другие LiveData
LiveDataValidator умеет следить за другими LiveData и реагировать на их изменения
Для этого есть метод watchOn
liveDataValidator.watchOn(textMaxLength) < newTextMaxLength ->liveDataValidator.validate() >
В примере выше liveDataValidator следит за полем textMaxLength и как только значение textMaxLength меняется liveDataValidator принудительно валидируется
Для подобных случаев есть метод triggerOn , который запускает валидацию всякий раз когда изменяется дополнительный источник
liveDataValidator.triggerOn(textMaxLength)
Есть 2 текстовых поля: на одном пики точены, на другом х** д*ы вовсе не пики Задача, чтобы второе поле не содержало в себе текст первого поля
val first: MutableLiveData = MutableLiveData() //Первое поле (с пиками) val second: MutableLiveData = MutableLiveData() //Второе поле (с другими пиками) val secondValidator: LiveDataValidator = LiveDataValidator(second).apply < addCondition(Conditions.RequiredField()) addCondition(Conditions.RegEx(«[a-z]+».toRegex(), «only a-z symbols allowed»)) addCondition(Conditions.TextMaxLength(10)) addCondition < // Внимание сюда: для проверки используется внешнее мутабельное поле first! if (it?.contains(first.value ?: «») == true) < ValidationResult.invalid(«textField2 should not contains textField1») >else < ValidationResult.valid() >> triggerOn(first) //Теперь при каждом изменении first будет вызываться метод validate() >
Как видно, secondValidator проверяет поле second , но при этом использует исползует first для проверки. Но что если first изменился? Тогда валидатор будет висеть в неактуальном состоянии до следующего изменения second . Поэтому валидатору нужно следить за first и при каждом его изменении принудительно выполнять проверку Делается это методом triggerOn(LiveData) , который будет запускать валидатор при каждом изменении first
Вместо triggerOn можно так же использовать watchOn и самостоятельно прописать нужное действие
watchOn(textField1)
MuxLiveDataValidator — объединяем валидаторы
А теперь, когда у нас есть куча полей с LiveDataValidator’ами надо каким-то образом опредилить общий результат валидации. Самый распространённый пример: если все поля на форме заполнены правильно — включаем кнопку «Далее».
Для этого есть MuxLiveDataValidator . Он подписывается на множество LiveDataValidator’ов и как только один из них изменяется — MuxLiveDataValidator собирает состояния ( ValidationResult ) всех LiveDataValidator’ов и отдаёт их на проверку оператору ( Operator ). Operator выдаёт окончательный результат.
Короче, MuxLiveDataValidator работает типа как мультиплексор. Отсюда и название.
Состояние (state)
Аналогично LiveDataValidator у MuxLiveDataValidator есть состояние
muxValidator.state
Состояние это LiveData в котором находится последний результат проверки.
Активация MuxLiveDataValidator
Тут как у LiveDataValidator — доступ только по подписке
viewModel.muxValidator.observe(viewLifecycleOwner) < validationResult ->// apply validatioin result >
Когда вы подписываетесь на MuxLiveDataValidator , то все его LiveDataValidator активируются, то есть подписка распространяется и на них (такой вот аналог семейной подписки у MediatorLiveData ). То есть если вы подписались на MuxLiveDataValidator , то не можно не подписываться на те LiveDataValidator , за которыми он следит.
Добавление валидатора
Добавить LiveDataValidator можно при создании MuxLiveDataValidator
val muxValidator = MuxLiveDataValidator( textField1Validator, textField2Validator )
Можно и после создания
muxValidator.addValidator(textField3Validator) //Можешь докинуть сразу несколько muxValidator.addValidators( listOf( textField4Validator, textField5Validator ) )
Удаление валидатора
Ну тут типа ваще всё изян
muxValidator.removeValidator(textField3Validator)
Установка оператора
По-умолчанию MuxLiveDataValidator использует оператор-конъюнкцию. Чтобы поменять логику выдачи финального ValidationResult нужно установить другой оператор
muxValidator.setOperator(Validator.Operator.Disjunction())
Есть возможность следить за сменой оператора чтобы, например, очистить ошибку на view.
muxValidator.addOperatorChangedListener < // on operator changed >//Удалить слушателя можно примерно вот так muxValidator.removeOperatorChangedListener(listener)
Подключение валидаторов к view
ConditionViewBinder
ConditionViewBinder базовый связыватель view и Condition
В момент вызова ConditionViewBinder.validate() достает из view данные для проверки абстрактным методом getValidationData() . Эти данные улетают в Condition , который проверит их и вернет ValidationResult . Затем этот ValidationResult передаётся абстрактному методу onValidationResult() в котором и происходит изменения view.
val editText1 = requireView().findViewById(R.id.edit_text1) val condition = Conditions.TextMaxLength(10) val conditionBinder = object : ConditionViewBinder(WeakReference(editText1), condition) < override fun getValidationData(view: TextView?): String? < return view?.text?.toString() >override fun onValidationResult(view: TextView?, result: ValidationResult?) < if (result?.isValid == true) < view?.error = null >else < view?.error = result?.errorMessage >> > conditionBinder.check()
Таким образом можно привязать любой валидатор к любой view
ValidatorViewBinder
Предназначен для более удобной работы с Validator : следит за изменениями оператора и условий валидатора.
LiveDataValidatorViewBinder
LiveDataValidator — особый пациент. Для него свой binder, который:
- сам подписывается/отписывается на LiveDataValidator ( чтобы активировать его)
- getValidationData() берется не из view, а прямо из валидатора (из его source )
LiveDataValidatorViewBinder нужно активировать. Тут 2 способа:
-
Через конструктор. В конструктор передать LifeycleOwner
object : LiveDataValidatorViewBinder( viewLifecycleOwner, WeakReference(binding.editText1), viewModel.textField1Validator) < override fun onValidationResult(view: TextView?, result: ValidationResult?) < >override fun onConditionsChanged(conditions: Set>) < >override fun onOperatorChanged() < >>
liveDataValidatorViewBinder.attach(viewLifecycleOwner)
Готовые реализации
TextConditionViewBinder
Связывает простые Condition с TextView . Проверяет поле при каждом изменении текста в нём
val editText1 = requireView().findViewById(R.id.edit_text1) val condition = Conditions.TextMaxLength(10) editText.validateBy(condition)
TextViewLiveDataValidatorBinder
Тут то же самое, что и TextConditionViewBinder , но тут работаем с LiveDataValidator .
val editText = requireView().findViewById(R.id.edit_text1) val liveDataValidator = LiveDataValidator(viewModel.textField1, Conditions.RequiredField()) editText.validateBy(viewLifecycleOwner, liveDataValidator)
Примеры
Простая валидация
- Во ViewModel делаем простейший Condition
val textFieldCondition = Conditions.RegEx( «[a-z]+».toRegex(), «only a-z symbols allowed» )
val editText = requireView().findViewById(R.id.edit_text1) editText.validateBy(viewModel.textFieldCondition)
Сложная валидация
Допустим у нас есть 3 поля: поле для ввода цифр, поле для ввода букв и поле, которое указывает максимальную длину поля ввода цифр. О как! А ещё нужно выводить общее состояние валидации всей формы в отдельное текстовое поле!
-
Для начала объявим сами поля и валидаторы к ним во ViewModel]
//Поле, которое определяет максимальную длину поля для ввода цифр val textMaxLength: MutableLiveData = MutableLiveData() //Цифровое поле val textField1: MutableLiveData = MutableLiveData() //Про этот валидатор — чуть ниже val textField1Validator = ExampleValidators.DigitsFieldValidator(textField1).apply < watchOn(textMaxLength) < val maxLength = kotlin.runCatching < it?.toInt() >.getOrNull() this.setMaxLength(maxLength) > > //Буквенное поле val textField2: MutableLiveData = MutableLiveData() val textField2Validator: LiveDataValidator = LiveDataValidator(textField2).apply < addCondition(Conditions.RequiredField()) addCondition(Conditions.RegEx(«[a-z]+».toRegex(), «only a-z symbols allowed»)) addCondition(Conditions.TextMaxLength(10)) >//Обобщенный валидатор val muxValidator = MuxLiveDataValidator( textField1Validator, textField2Validator )
class ExampleValidators < class DigitsFieldValidator( source: LiveData, initialCondition: Condition? = null, operator: Operator = Operator.Conjunction() ) : LiveDataValidator( source, initialCondition, operator ) < val onlyDigitsCondition = Conditions.RegEx(«[0-9]+».toRegex(), «only digits allowed») private var maxLengthCondition = Conditions.TextMaxLength(5) //по-умолчанию пусть будет 5 init < addCondition(onlyDigitsCondition) addCondition(maxLengthCondition) >fun setMaxLength(maxLength: Int?) < if (maxLength == null || maxLength < 0) < removeCondition(maxLengthCondition) return >val newCondition = Conditions.TextMaxLength(maxLength) changeConditionsSet < remove(maxLengthCondition) maxLengthCondition = newCondition add(maxLengthCondition) >> > >
override fun onViewCreated(view: View, savedInstanceState: Bundle?) < super.onViewCreated(view, savedInstanceState) viewModel = ViewModelProvider(this).get(ExampleViewModel1::class.java) binding.viewModel = viewModel // Подключаем валидатор к цифровому полю binding.editText1.validateBy( viewLifecycleOwner, viewModel.textField1Validator ) // Подключаем валидатор к буквенному полю binding.editText2.validateBy( viewLifecycleOwner, viewModel.textField2Validator ) //Следим за обобщенным (mux) валидатором viewModel.muxValidator.observe(viewLifecycleOwner) < setGeneralValidationResult(it) >> //Отображем результат общей валидации в отдельном текстовом поле «state» private fun setGeneralValidationResult(validationResult: ValidationResult) < if (validationResult.isValid) < binding.state.text = «Correct!» binding.state.setTextColor(ContextCompat.getColor(requireContext(), R.color.state_success)) >else < binding.state.text = validationResult.errorMessage ?: «Error message is null» binding.state.setTextColor(ContextCompat.getColor(requireContext(), R.color.design_default_color_error)) >>
Готово!
Общие рекомендации по использованию
- Все валидаторы должны находиться во ViewModel (ну или в Presenter) Не надо выносить логику валидирования во фрагменты, активности и вообще на view уровень.
- По-возможности используйте LiveDataValidator . Он самый прокаченный. И вообще вся библиотека ради него написана была
- Аккуратнее с множеством условий. Вы можете добавить на поле противоречащие друг другу условия и будет непонятно что!
- Делайте свои реализации. Создавайте свои ConditionViewBinder ы, чтобы работать с кастомными view Создавайте свои валидаторы если вам нужна более сложная валидация
- Разработка под Android
- Kotlin
Источник: habr.com