Skip to content

Instantly share code, notes, and snippets.

@kant2002
Created February 28, 2024 15:05
Show Gist options
  • Save kant2002/5c716d6a4aab1dd5de3c7cdb1f3a2913 to your computer and use it in GitHub Desktop.
Save kant2002/5c716d6a4aab1dd5de3c7cdb1f3a2913 to your computer and use it in GitHub Desktop.
Тестування на базі властивостей
#r "nuget: FsCheck, 3.0.0-rc2"
#r "nuget: FSharp.Core.Ukrainian, 0.0.6"
open FsCheck
open FsCheck.FSharp
type ТипПалива = Дизель | Бензін | Електрика | Гибрид | REXГибрид
type НапрямокПродаж = Казахстан | Киргизстан
type Авто = {
Паливо:ТипПалива
РікВиробництва :int
Об'ємДвигуна: int option
МодельнийРік :int
ЦінаEXW :int option
ЗаводськаЦіна: int
}
let розрахуватиЦіну (авто: Авто) напрямокПродаж =
let yuanДоUsd = 0.1369
let kztДоUsd = 0.002096
let типПалива = авто.Паливо
let рікВиробництва = авто.РікВиробництва
let цінаExw =
авто.ЦінаEXW
|> Option.map float
|> Option.defaultValue ((авто.ЗаводськаЦіна |> float) * yuanДоUsd + 1500.0)
match напрямокПродаж with
| Киргизстан ->
{| ЦінаEXW = цінаExw; МРП = None; ЦінаЕТТ = None; ЦінаВТО = None; НДВ = None; ЛьготнаЦіна = None; СбориКомпанії = None; ПервинаРеєстрация = None; УтильЗбір = None |}
| Казахстан ->
let рік = System.DateTime.Now.Year
let мрп = kztДоUsd * if рік = 2023 then 3450.0 else 3692.0
let первиннаРеєстрация =
мрп *
match рік - рікВиробництва with
| x when x <= 0 -> 0.25
| x when x > 0 && x < 3 -> 50.
| _ -> 500.0
let митнийЗбір = 20_000.0 * kztДоUsd
let сбір_компанії = 500.0
let утильЗбір =
50. * мрп *
match типПалива with
| Дизель | Бензін | Гибрид | REXГибрид ->
match авто.Об'ємДвигуна with
| Some об'ємДвигуна when об'ємДвигуна < 1000 -> 1.5
| Some об'ємДвигуна when об'ємДвигуна >= 1000 && об'ємДвигуна < 2000 -> 3.5
| Some об'ємДвигуна when об'ємДвигуна >= 2000 && об'ємДвигуна < 3000 -> 5.
| Some об'ємДвигуна when об'ємДвигуна >= 3000 -> 11.5
| _ -> 0.
| _ -> 0.
match типПалива with
| Дизель | Бензін | Гибрид ->
let митнаЦіна = цінаExw + митнийЗбір
let митнийПлатіж = митнаЦіна * 0.15
let НДС = митнаЦіна * 0.12
let цінаЕТТ = митнаЦіна + митнийПлатіж + НДС + утильЗбір + сбір_компанії + первиннаРеєстрация
{| ЦінаEXW = цінаExw; МРП = Some(мрп); ЦінаЕТТ = Some цінаЕТТ; ЦінаВТО = None; НДВ = None; СбориКомпанії = Some сбір_компанії; ЛьготнаЦіна = None; ПервинаРеєстрация = Some первиннаРеєстрация; УтильЗбір = Some утильЗбір |}
| _ ->
let льготнаЦіна = цінаExw + сбір_компанії + первиннаРеєстрация + утильЗбір
let митнаЦіна = цінаExw + митнийЗбір
let НДВ = митнаЦіна * 0.12
let цінаВТО = митнаЦіна + НДВ + утильЗбір + сбір_компанії + первиннаРеєстрация
let митнийПлатіж = митнаЦіна * 0.15
let цінаЕТТ = митнаЦіна + митнийПлатіж + НДВ + утильЗбір + сбір_компанії + первиннаРеєстрация
{| ЦінаEXW = цінаExw; МРП = Some(мрп); ЦінаЕТТ = Some цінаЕТТ; ЦінаВТО = Some цінаВТО; НДВ = Some НДВ; ЛьготнаЦіна = Some льготнаЦіна; СбориКомпанії = Some сбір_компанії; ПервинаРеєстрация = Some первиннаРеєстрация; УтильЗбір = Some утильЗбір |}
// =========================================== Тесты =========================================
let потрібен_НДВ авто =
авто.Паливо = Електрика || авто.Паливо = REXГибрид
let ``НДВ для Киргизстану не потрібен`` авто напрямокПродаж =
(напрямокПродаж = Киргизстан) ==>
(lazy ((розрахуватиЦіну авто напрямокПродаж).НДВ = None))
Check.Quick ("НДВ для Киргизстану не потрібен", ``НДВ для Киргизстану не потрібен``)
let построительАвто паливо об'ємДвигуна рікВипуску =
{
Паливо = паливо
РікВиробництва = рікВипуску
Об'ємДвигуна = Some(об'ємДвигуна)
МодельнийРік = 2022
ЦінаEXW = None
ЗаводськаЦіна = 0
}
let генераторТипаПалива = ArbMap.defaults |> ArbMap.generate<ТипПалива>
let генераторОб'ємаДвигуна = Gen.choose (0, 50) |> Gen.map (fun x -> x * 100)
let генераторРокуВиробництва = Gen.choose (0, 10) |> Gen.map (fun x -> System.DateTime.Now.Year - x)
let генераторАвто = Gen.map3 построительАвто генераторТипаПалива генераторОб'ємаДвигуна генераторРокуВиробництва
type ГенераториАвто =
static member Авто() =
{new Arbitrary<Авто>() with
override _.Generator = генераторАвто
override _.Shrinker _ = Seq.empty }
let конфигурація =
Config.Quick
.WithArbitrary([typeof<ГенераториАвто>])
.WithMaxRejected(20_000)
let утильЗбірУМРП авто напрямПродаж пропорції =
let ціна = розрахуватиЦіну авто напрямПродаж
match(ціна.УтильЗбір, ціна.МРП) with
| Some(утильЗбір), Some(мрп) when мрп * пропорції - утильЗбір < 1. -> true
| _ -> false
|@ (sprintf "Утиль збір = %A, МРП = %A" ціна.УтильЗбір ціна.МРП)
type ``Правила Казахстана`` =
static member ``Утильзбір для електромобілей не збирається`` авто =
(авто.Паливо = Електрика) ==>
(lazy ((розрахуватиЦіну авто Казахстан).УтильЗбір = Some(0.)))
static member ``Утильзбір для авто меньш 1000 мл`` авто =
((авто.Паливо <> Електрика) && авто.Об'ємДвигуна |> Option.map(fun x -> x < 1000) = Some(true)) ==>
(lazy утильЗбірУМРП авто Казахстан 75.)
static member ``Утильзбір для авто від 1000 мл до 2000 мл`` авто =
((авто.Паливо <> Електрика) && авто.Об'ємДвигуна |> Option.map(fun x -> x < 2000 && x >= 1000) = Some(true)) ==>
(lazy утильЗбірУМРП авто Казахстан 175.)
static member ``Утильзбір для авто від 2000 мл до 3000 мл`` авто =
((авто.Паливо <> Електрика) && авто.Об'ємДвигуна |> Option.map(fun x -> x < 3000 && x >= 2000) = Some(true)) ==>
(lazy утильЗбірУМРП авто Казахстан 250.)
static member ``Утильзбір для авто від 3000 мл та вище`` авто =
((авто.Паливо <> Електрика) && авто.Об'ємДвигуна |> Option.map(fun x -> x >= 3000) = Some(true)) ==>
(lazy утильЗбірУМРП авто Казахстан 575.)
static member ``НДВ збирається для електромобілей та REX-гибридів`` авто =
(потрібен_НДВ авто) ==>
(lazy ((розрахуватиЦіну авто Казахстан).НДВ <> None))
static member ``НДВ не собирается для звичайних гибридів та звичайних авто`` авто =
не (потрібен_НДВ авто) ==>
(lazy ((розрахуватиЦіну авто Казахстан).НДВ = None))
Check.All<``Правила Казахстана``>(конфигурація)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment