Compare commits
5 Commits
second-lab
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 71de5751fe | |||
| ab268624bf | |||
| 7596e5632c | |||
| 035ea70161 | |||
| ff5b5bb44e |
@@ -2,7 +2,14 @@
|
||||
|
||||
|
||||
def fix_encoding(text):
|
||||
fixed_text = text.encode("latin1").decode("windows-1251")
|
||||
result = []
|
||||
for ch in text:
|
||||
try:
|
||||
decoded = ch.encode("latin1").decode("windows-1251")
|
||||
result.append(decoded)
|
||||
except (UnicodeEncodeError, UnicodeDecodeError):
|
||||
result.append(ch)
|
||||
fixed_text = "".join(result)
|
||||
fixed_text = fixed_text.replace("ј", "ё")
|
||||
fixed_text = fixed_text.replace("ѕ", "<<")
|
||||
fixed_text = fixed_text.replace("ї", ">>")
|
||||
|
||||
1
lab4/.gitignore
vendored
Normal file
1
lab4/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
other
|
||||
9
lab4/calctests/.gitattributes
vendored
Normal file
9
lab4/calctests/.gitattributes
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
5
lab4/calctests/.gitignore
vendored
Normal file
5
lab4/calctests/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
# Ignore Gradle project-specific cache directory
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle build output directory
|
||||
build
|
||||
3
lab4/calctests/.vscode/settings.json
vendored
Normal file
3
lab4/calctests/.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "interactive"
|
||||
}
|
||||
45
lab4/calctests/app/build.gradle
Normal file
45
lab4/calctests/app/build.gradle
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* This generated file contains a sample Java application project to get you started.
|
||||
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.8/userguide/building_java_projects.html in the Gradle documentation.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the application plugin to add support for building a CLI application in Java.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Use Maven Central for resolving dependencies.
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Use JUnit Jupiter for testing.
|
||||
testImplementation libs.junit.jupiter
|
||||
|
||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
|
||||
// This dependency is used by the application.
|
||||
implementation libs.guava
|
||||
|
||||
implementation files('./libs/calculator-1.0.jar')
|
||||
}
|
||||
|
||||
// Apply a specific Java toolchain to ease working on different environments.
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'dev.tishenko.calctests.App'
|
||||
}
|
||||
|
||||
tasks.named('test') {
|
||||
// Use JUnit Platform for unit tests.
|
||||
useJUnitPlatform()
|
||||
}
|
||||
BIN
lab4/calctests/app/libs/calculator-1.0.jar
Normal file
BIN
lab4/calctests/app/libs/calculator-1.0.jar
Normal file
Binary file not shown.
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This source file was generated by the Gradle 'init' task
|
||||
*/
|
||||
package dev.tishenko.calctests;
|
||||
|
||||
public class App {
|
||||
public String getGreeting() {
|
||||
return "Hello World!";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(new App().getGreeting());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This source file was generated by the Gradle 'init' task
|
||||
*/
|
||||
package dev.tishenko.calctests;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.epam.tat.module4.Calculator;
|
||||
|
||||
class CalculatorTest {
|
||||
private static final double DELTA = 0.0001;
|
||||
private Calculator calculator;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
calculator = new Calculator();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1, 2, 3",
|
||||
"5, 0, 5",
|
||||
"-7, 7, 0",
|
||||
"9223372036854775806, 1, 9223372036854775807"
|
||||
})
|
||||
void testLongSum(long a, long b, long expected) {
|
||||
assertEquals(expected, calculator.sum(a, b));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1.5, 2.5, 4.0",
|
||||
"5.5, 0.0, 5.5",
|
||||
"-3.5, 3.5, 0.0",
|
||||
"0.1, 0.2, 0.3"
|
||||
})
|
||||
void testDoubleSum(double a, double b, double expected) {
|
||||
assertEquals(expected, calculator.sum(a, b), DELTA);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"2.5, 3.0, 7.5",
|
||||
"0.0, 5.5, 0.0",
|
||||
"-2.5, 3.0, -7.5",
|
||||
"-2.5, -3.0, 7.5"
|
||||
})
|
||||
void testDoubleMult(double a, double b, double expected) {
|
||||
assertEquals(expected, calculator.mult(a, b), DELTA);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"2, 3, 6",
|
||||
"0, 5, 0",
|
||||
"-2, 3, -6",
|
||||
"-2, -3, 6",
|
||||
"1000, 1000, 1000000"
|
||||
})
|
||||
void testLongMult(long a, long b, long expected) {
|
||||
assertEquals(expected, calculator.mult(a, b));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { 4.0, 0.0, -4.0, 1000000.0 })
|
||||
void testSqrt(double value) {
|
||||
double expected = Math.sqrt(value);
|
||||
assertEquals(expected, calculator.sqrt(value), DELTA);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { 0, Math.PI / 6, Math.PI / 4, -Math.PI / 3, 10 })
|
||||
void testTg(double angle) {
|
||||
double expected = Math.tan(angle);
|
||||
double actual = calculator.tg(angle);
|
||||
assertEquals(expected, actual, 0.0001);
|
||||
}
|
||||
}
|
||||
10
lab4/calctests/gradle/libs.versions.toml
Normal file
10
lab4/calctests/gradle/libs.versions.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file was generated by the Gradle 'init' task.
|
||||
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
||||
|
||||
[versions]
|
||||
guava = "33.0.0-jre"
|
||||
junit-jupiter = "5.10.2"
|
||||
|
||||
[libraries]
|
||||
guava = { module = "com.google.guava:guava", version.ref = "guava" }
|
||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
|
||||
BIN
lab4/calctests/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
lab4/calctests/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
lab4/calctests/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
lab4/calctests/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
249
lab4/calctests/gradlew
vendored
Normal file
249
lab4/calctests/gradlew
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
92
lab4/calctests/gradlew.bat
vendored
Normal file
92
lab4/calctests/gradlew.bat
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
14
lab4/calctests/settings.gradle
Normal file
14
lab4/calctests/settings.gradle
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.8/userguide/multi_project_builds.html in the Gradle documentation.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
// Apply the foojay-resolver plugin to allow automatic download of JDKs
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
|
||||
}
|
||||
|
||||
rootProject.name = 'calctests'
|
||||
include('app')
|
||||
7
lab4/report/.gitignore
vendored
Normal file
7
lab4/report/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
**/*
|
||||
!.gitignore
|
||||
!report.tex
|
||||
!img
|
||||
!img/**
|
||||
!programm
|
||||
!programm/*.py
|
||||
BIN
lab4/report/img/selenium-tests.png
Normal file
BIN
lab4/report/img/selenium-tests.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
lab4/report/img/test1.png
Normal file
BIN
lab4/report/img/test1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
lab4/report/img/test2.png
Normal file
BIN
lab4/report/img/test2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
BIN
lab4/report/img/test3.png
Normal file
BIN
lab4/report/img/test3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
lab4/report/img/test4.png
Normal file
BIN
lab4/report/img/test4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
845
lab4/report/report.tex
Normal file
845
lab4/report/report.tex
Normal file
@@ -0,0 +1,845 @@
|
||||
\documentclass[a4paper, final]{article}
|
||||
%\usepackage{literat} % Нормальные шрифты
|
||||
\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта
|
||||
\usepackage{tabularx}
|
||||
\usepackage[T2A]{fontenc}
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[russian]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry}
|
||||
\usepackage{ragged2e} %для растягивания по ширине
|
||||
\usepackage{setspace} %для межстрочно го интервала
|
||||
\usepackage{moreverb} %для работы с листингами
|
||||
\usepackage{indentfirst} % для абзацного отступа
|
||||
\usepackage{moreverb} %для печати в листинге исходного кода программ
|
||||
\usepackage{pdfpages} %для вставки других pdf файлов
|
||||
\usepackage{tikz}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{afterpage}
|
||||
\usepackage{longtable}
|
||||
\usepackage{float}
|
||||
|
||||
|
||||
|
||||
% \usepackage[paper=A4,DIV=12]{typearea}
|
||||
\usepackage{pdflscape}
|
||||
% \usepackage{lscape}
|
||||
|
||||
\usepackage{array}
|
||||
\usepackage{multirow}
|
||||
|
||||
\renewcommand\verbatimtabsize{4\relax}
|
||||
\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге
|
||||
\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице
|
||||
\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы
|
||||
\usepackage{listings} %листинги
|
||||
\usepackage{xcolor} % цвета
|
||||
\usepackage{hyperref}% для гиперссылок
|
||||
\usepackage{enumitem} %для перечислений
|
||||
|
||||
\newcommand{\specialcell}[2][l]{\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}}
|
||||
|
||||
|
||||
\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях
|
||||
|
||||
\hypersetup{colorlinks,
|
||||
allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные)
|
||||
|
||||
% подгружаемые языки — подробнее в документации listings (это всё для листингов)
|
||||
\lstloadlanguages{ Java}
|
||||
% включаем кириллицу и добавляем кое−какие опции
|
||||
\lstset{tabsize=2,
|
||||
breaklines,
|
||||
basicstyle=\footnotesize,
|
||||
columns=fullflexible,
|
||||
flexiblecolumns,
|
||||
numbers=left,
|
||||
numberstyle={\footnotesize},
|
||||
keywordstyle=\color{blue},
|
||||
inputencoding=cp1251,
|
||||
extendedchars=true
|
||||
}
|
||||
\lstdefinelanguage{MyC}{
|
||||
language=Java,
|
||||
% ndkeywordstyle=\color{darkgray}\bfseries,
|
||||
% identifierstyle=\color{black},
|
||||
% morecomment=[n]{/**}{*/},
|
||||
% commentstyle=\color{blue}\ttfamily,
|
||||
% stringstyle=\color{red}\ttfamily,
|
||||
% morestring=[b]",
|
||||
% showstringspaces=false,
|
||||
% morecomment=[l][\color{gray}]{//},
|
||||
keepspaces=true,
|
||||
escapechar=\%,
|
||||
texcl=true
|
||||
}
|
||||
|
||||
\textheight=24cm % высота текста
|
||||
\textwidth=16cm % ширина текста
|
||||
\oddsidemargin=0pt % отступ от левого края
|
||||
\topmargin=-1.5cm % отступ от верхнего края
|
||||
\parindent=24pt % абзацный отступ
|
||||
\parskip=5pt % интервал между абзацами
|
||||
\tolerance=2000 % терпимость к "жидким" строкам
|
||||
\flushbottom % выравнивание высоты страниц
|
||||
|
||||
|
||||
% Настройка листингов
|
||||
\lstset{
|
||||
language=Java,
|
||||
extendedchars=\true,
|
||||
inputencoding=utf8,
|
||||
keepspaces=true,
|
||||
% captionpos=b, % подписи листингов снизу
|
||||
}
|
||||
|
||||
\begin{document} % начало документа
|
||||
|
||||
|
||||
|
||||
% НАЧАЛО ТИТУЛЬНОГО ЛИСТА
|
||||
\begin{center}
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\
|
||||
федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]}
|
||||
\normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt]
|
||||
\normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt]
|
||||
\normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\
|
||||
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\hfill \break
|
||||
\large{Лабораторная работа №4}\\
|
||||
\large{<<Автоматизированное тестирование>>}\\
|
||||
\large{по дисциплине}\\
|
||||
\large{<<Методы тестирования программного обеспечения>>}\\
|
||||
\hfill \break
|
||||
|
||||
% \hfill \break
|
||||
\hfill \break
|
||||
\end{center}
|
||||
|
||||
\small{
|
||||
\begin{tabular}{lrrl}
|
||||
\!\!\!Студент, & \hspace{2cm} & & \\
|
||||
\!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\
|
||||
\!\!\!Преподаватель & \hspace{2cm} & \underline{\hspace{3cm}} & Курочкин М. А. \\\\
|
||||
&&\hspace{4cm}
|
||||
\end{tabular}
|
||||
\begin{flushright}
|
||||
<<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2025г.
|
||||
\end{flushright}
|
||||
}
|
||||
|
||||
\hfill \break
|
||||
% \hfill \break
|
||||
\begin{center} \small{Санкт-Петербург, 2025} \end{center}
|
||||
\thispagestyle{empty} % выключаем отображение номера для этой страницы
|
||||
|
||||
% КОНЕЦ ТИТУЛЬНОГО ЛИСТА
|
||||
\newpage
|
||||
|
||||
\tableofcontents
|
||||
|
||||
|
||||
\newpage
|
||||
|
||||
\section{Постановка задачи}
|
||||
|
||||
Данная лабораторная работа делится на две части. В первой части необходимо разработать набор юнит-тестов к предоставленной библиотеке calculator.jar, которая содержит методы для проведения разнообразных операций над числами. Во второй части необходимо протестировать сайт в Chrome путем написания двух тестов, проверяющих корректность отображения страниц. Использовать для тестирования Selenuim WebDriver.
|
||||
|
||||
|
||||
\newpage
|
||||
\section {Средства автоматизации тестирования}
|
||||
\subsection{JUinit}
|
||||
\textit{JUnit} — это фреймворк, созданный для тестирования программного обеспечения на языке Java. Он предназначен для разработки и выполнения автоматизированных тестов, что дает разработчикам возможность проверять правильность функционирования своего кода и обнаруживать ошибки на ранних стадиях разработки.
|
||||
|
||||
|
||||
\subsubsection{Основные особенности JUnit}
|
||||
\begin{itemize}
|
||||
\item\textbf{ Модульное тестирование:} JUnit поддерживает тестирование отдельных модулей, позволяя разработчикам проверять работу отдельных компонентов (методов и классов) независимо друг от друга.
|
||||
\item\textbf{ Аннотации:} JUnit использует аннотации, такие как \texttt{@Test}, \texttt{@Before}, \texttt{@After}, которые упрощают написание тестов и делают код более читабельным. Например, аннотация \texttt{@Before }позволяет выполнять определенный код перед каждым тестом, а @After — после его завершения.
|
||||
\item \textbf{Ассерты: }JUnit предоставляет различные методы ассертов, такие как assertEquals, assertTrue, assertNotNull, которые помогают проверять ожидаемые результаты тестов.
|
||||
\item \textbf{Группировка тестов:} Тесты могут быть сгруппированы с помощью аннотации @Suite, что позволяет запускать их вместе.
|
||||
\item \textbf{ Интеграция:} JUnit просто интегрируется с различными инструментами и фреймворками, такими как Maven, Gradle и широко используемые IDE, включая Eclipse и IntelliJ IDEA, что упрощает процесс тестирования.
|
||||
|
||||
\end{itemize}
|
||||
\subsubsection{ Преимущества использования JUnit}
|
||||
\begin{itemize}
|
||||
\item \textbf{Упрощение процесса тестирования:} JUnit делает написание тестов более удобным и структурированным.
|
||||
\item \textbf{Автоматизация:} Позволяет автоматизировать тесты, что снижает вероятность ошибок и повышает качество кода.\par
|
||||
\item \textbf{Поддержка непрерывной интеграции:} JUnit хорошо совместим с системами непрерывной интеграции, позволяя запускать тесты автоматически при каждом изменении кода.
|
||||
\item \textbf{Снижение затрат на отладку:} Регулярное тестирование помогает выявлять проблемы на ранних стадиях, что уменьшает расходы на их исправление.
|
||||
\end{itemize}
|
||||
\subsubsection{Функционал библиотеки}
|
||||
JUnit имеет широкий функционал для проверки совпадения ожидаемого резульата, и результата полученного тестируемым методом.\par
|
||||
\vspace{5pt}
|
||||
Класс \texttt{junit.framework.Assert} предоставляет набор статических методов для проверки различных условий в тестах.
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{assertEquals(expected, actual)} - проверяет равенство двух значений. Если значения не равны, тест завершается с ошибкой. Имеет перегрузки для различных типов данных.
|
||||
|
||||
\item \texttt{assertFalse(condition)} - проверяет, что переданное булево значение является \texttt{false}. Если значение \texttt{true}, тест завершается с ошибкой.
|
||||
|
||||
\item \texttt{assertNotNull(object)} - проверяет, что объект не является \texttt{null}. Если объект \texttt{null}, тест завершается с ошибкой.
|
||||
|
||||
\item \texttt{assertNull(object)} - проверяет, что объект является \texttt{null}. Если объект не \texttt{null}, тест завершается с ошибкой.
|
||||
|
||||
\item \texttt{assertNotSame(unexpected, actual)} - проверяет, что два объекта не ссылаются на один и тот же экземпляр. Если ссылки идентичны, тест завершается с ошибкой.
|
||||
|
||||
\item \texttt{assertSame(expected, actual)} - проверяет, что два объекта ссылаются на один и тот же экземпляр. Если ссылки разные, тест завершается с ошибкой.
|
||||
|
||||
\item \texttt{assertTrue(condition)} - проверяет, что переданное булево значение является \texttt{true}. Если значение \texttt{false}, тест завершается с ошибкой.
|
||||
\end{itemize}
|
||||
|
||||
Класс \texttt{junit.framework.TestCase} наследуется от \texttt{junit.framework.Assert} и предоставляет базовую функциональность для создания тестовых случаев.
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{run()} - основной метод, выполняющий тест. Содержит логику запуска и выполнения тестового случая.
|
||||
|
||||
\item \texttt{setUp()} - метод, выполняемый перед каждым тестом. Используется для инициализации тестового окружения и подготовки данных. В аннотационной версии JUnit 4+ заменён на \texttt{@Before}.
|
||||
|
||||
\item \texttt{tearDown()} - метод, выполняемый после каждого теста. Используется для очистки ресурсов после выполнения теста. В аннотационной версии JUnit 4+ заменён на \texttt{@After}.
|
||||
\end{itemize}
|
||||
\subsubsection{Этапы написания тестов}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Реализация теста}: Написание тестового метода и аннотирование его с помощью. \texttt{@Test}
|
||||
\item \textbf{Настройка и очистка} Использование аннотаций \texttt{@Before} и \texttt{@After}
|
||||
для выполнения операйи перед и после теста.
|
||||
\item \textbf{Запуск тестов:} Использование встроенных средств IDE или командной строки для выполнения тестов.
|
||||
\end{enumerate}
|
||||
\subsection{Selenium WebDriver}
|
||||
\textit{Selenium WebDriver } --- это фреймворк с открытым исходным кодом для автоматизации тестирования веб-приложений. Он предоставляет программный интерфейс для взаимодействия с браузерами, позволяя эмулировать действия пользователя на веб-страницах.
|
||||
\textbf{Основные особенности Selenium WebDriver}:
|
||||
\begin{itemize}
|
||||
\item \textbf{Кроссбраузерность:} Поддержка всех популярных браузеров, включая Chrome,
|
||||
Firefox, Safari, Edge и Opera.
|
||||
\item \textbf{Многоязычность:} Возможность написания тестовых скриптов на различных
|
||||
языках программирования — Java, Python, C\#, Ruby, JavaScript, PHP и Perl.
|
||||
\item \textbf{Прямое взаимодействие:} WebDriver напрямую отправляет команды браузеру и
|
||||
получает результаты, что обеспечивает более точное воспроизведение
|
||||
пользовательских действий.
|
||||
\item \textbf{Кроссплатформенность:} Возможность запуска тестов на различных операционных
|
||||
системах (Windows, MacOS, Linux).
|
||||
\item \textbf{Параллельное выполнение:} Поддержка одновременного запуска тестов в
|
||||
разных браузерах для ускорения тестирования.
|
||||
\end{itemize}\par
|
||||
|
||||
Архитектура Selenium WebDriver состоит из четырех основных компонентов:
|
||||
\begin{itemize}
|
||||
\item \textbf{Selenium Client Libraries:} Набор библиотек для различных языков
|
||||
программирования, позволяющих писать и запускать тесты на предпочитаемом языке.
|
||||
JSON Wire Protocol: REST API на основе JSON, обеспечивающий передачу
|
||||
информации между клиентом и сервером через HTTP.
|
||||
\item \textbf{Browser Drivers:} Специфичные для каждого браузера драйверы (ChromeDriver,
|
||||
GeckoDriver для Firefox и др.), которые получают команды и выполняют их
|
||||
в соответствующем браузере.
|
||||
\item \textbf{Browsers:} Сами браузеры, в которых выполняются тестовые сценарии.
|
||||
\end{itemize}
|
||||
\textbf{Этапы работы с WebDriver}:
|
||||
\begin{enumerate}
|
||||
\item \textbf{Инициализация:} Создание экземпляра WebDriver и открытие браузера.
|
||||
\item \textbf{Навигация:} Переход к нужной веб-странице с помощью метода get().
|
||||
\item \textbf{Поиск элементов:} Обнаружение элементов на странице с использованием
|
||||
различных локаторов (ID, XPath, CSS-селекторы и др.).
|
||||
\item \textbf{Взаимодействие:} Выполнение действий над элементами (клик, ввод текста,
|
||||
выбор из выпадающих списков и т.д.).
|
||||
\item \textbf{Ожидание:} Использование явных и неявных ожиданий для синхронизации
|
||||
с динамическими элементами страницы.
|
||||
\item \textbf{Проверка:} Получение информации о состоянии элементов и проверка результатов.
|
||||
\item \textbf{Завершение:} Закрытие браузера и освобождение ресурсов.
|
||||
\end{enumerate}
|
||||
Принцип выполнения команд:
|
||||
\begin{enumerate}
|
||||
\item Команда из тестового скрипта преобразуется в HTTP-запрос через JSON Wire Protocol.
|
||||
\item Запрос передается соответствующему драйверу браузера.
|
||||
\item Драйвер интерпретирует запрос и выполняет необходимые действия в браузере.
|
||||
\item Результат действия возвращается обратно в виде HTTP-ответа.
|
||||
\item Ответ преобразуется в формат, понятный тестовому скрипту.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
\newpage
|
||||
\section{Описание выполненных работ}
|
||||
\subsection{Работа №1}
|
||||
В ходе работы необходимо прописать юнит тесты для методов библиотеки calcualtor.jar, реализующий функционал калькулятора, производящего вычисления суммы, разности, умножения, деления, возведения в степень, ивзлечение корня, а также значений базовых тригонометрических функций. Дря реализации тестов, необходимо использовать JUnit.
|
||||
|
||||
\subsubsection{Класс CalculatorTest}
|
||||
Все тесты содержатся в классе CalculatorTest. В методе setUp() инициализируется объект \texttt{Calculator}. Константой DELTA задается допустимая погрешность. Код определения полей класса и метода setUp() представлен в листинге \ref{lst:CalculatorTest}.
|
||||
|
||||
\begin{lstlisting}[caption={Класс CalculatorTest}, label={lst:CalculatorTest}]
|
||||
class CalculatorTest {
|
||||
private static final double DELTA = 0.0001;
|
||||
private Calculator calculator;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
calculator = new Calculator();
|
||||
}
|
||||
}\end{lstlisting}
|
||||
|
||||
\subsubsection{Тесты для метода Sum}
|
||||
В классе CalculatorTest реализованы следующие тесты для метода sum:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{testLongSum} - тест для проверки суммы двух чисел типа long.
|
||||
\item \texttt{testDoubleSum} - тест для проверки суммы двух чисел типа double.
|
||||
\end{itemize}
|
||||
|
||||
Код тестов представлен в листинге \ref{lst:SumTest}. Тесты параметризованы с помощью аннотации \texttt{@ParameterizedTest} и \texttt{@CsvSource}.
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для метода Sum}, label={lst:SumTest}]
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1, 2, 3",
|
||||
"5, 0, 5",
|
||||
"-7, 7, 0",
|
||||
"9223372036854775806, 1, 9223372036854775807"
|
||||
})
|
||||
void testLongSum(long a, long b, long expected) {
|
||||
assertEquals(expected, calculator.sum(a, b));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"1.5, 2.5, 4.0",
|
||||
"5.5, 0.0, 5.5",
|
||||
"-3.5, 3.5, 0.0",
|
||||
"0.1, 0.2, 0.3"
|
||||
})
|
||||
void testDoubleSum(double a, double b, double expected) {
|
||||
assertEquals(expected, calculator.sum(a, b), DELTA);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Результаты запуска тестов:}
|
||||
|
||||
Результаты запуска тестов представлены на рисунке \ref{fig:test1}.
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.65\linewidth]{img/test1.png}
|
||||
\caption{Результаты запуска тестов для метода sum}
|
||||
\label{fig:test1}
|
||||
\end{figure}
|
||||
|
||||
По итогам запуска, метод sum прошел все тесты.
|
||||
|
||||
\subsubsection{Тесты для метода Mul}
|
||||
|
||||
В классе CalculatorTest реализованы следующие тесты для метода mul:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{testLongMul} - тест для проверки произведения двух чисел типа long.
|
||||
\item \texttt{testDoubleMul} - тест для проверки произведения двух чисел типа double.
|
||||
\end{itemize}
|
||||
|
||||
Код тестов представлен в листинге \ref{lst:MulTest}.
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для метода Mul}, label={lst:MulTest}]
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"2.5, 3.0, 7.5",
|
||||
"0.0, 5.5, 0.0",
|
||||
"-2.5, 3.0, -7.5",
|
||||
"-2.5, -3.0, 7.5"
|
||||
})
|
||||
void testDoubleMult(double a, double b, double expected) {
|
||||
assertEquals(expected, calculator.mult(a, b), DELTA);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({
|
||||
"2, 3, 6",
|
||||
"0, 5, 0",
|
||||
"-2, 3, -6",
|
||||
"-2, -3, 6",
|
||||
"1000, 1000, 1000000"
|
||||
})
|
||||
void testLongMult(long a, long b, long expected) {
|
||||
assertEquals(expected, calculator.mult(a, b));
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Результаты запуска тестов:}
|
||||
|
||||
Результаты запуска тестов представлены на рисунке \ref{fig:test2}.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.65\linewidth]{img/test2.png}
|
||||
\caption{Результаты запуска тестов для метода mul}
|
||||
\label{fig:test2}
|
||||
\end{figure}
|
||||
|
||||
По итогам запуска, метод mul для типа long прошел все тесты, а для типа double прошёл лишь 1 из 4 тестов.
|
||||
|
||||
\subsubsection{Тесты для метода Sqrt}
|
||||
|
||||
В классе CalculatorTest реализованы следующие тесты для метода sqrt:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{testSqrt} - тест для проверки квадратного корня числа типа double. Проверяет положительные, отрицательные значения, а также 0.
|
||||
\end{itemize}
|
||||
|
||||
Код тестов представлен в листинге \ref{lst:SqrtTest}.
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для метода Sqrt}, label={lst:SqrtTest}]
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { 4.0, 0.0, -4.0, 1000000.0 })
|
||||
void testSqrt(double value) {
|
||||
double expected = Math.sqrt(value);
|
||||
assertEquals(expected, calculator.sqrt(value), DELTA);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Результаты запуска тестов:}
|
||||
|
||||
Результаты запуска тестов представлены на рисунке \ref{fig:test3}.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.55\linewidth]{img/test3.png}
|
||||
\caption{Результаты запуска тестов для метода sqrt}
|
||||
\label{fig:test3}
|
||||
\end{figure}
|
||||
|
||||
По итогам запуска, метод sqrt не прошёл один из четырёх тестов. Метод неккоректно работает с отрицательными числами.
|
||||
|
||||
\subsubsection{Тесты для метода Tg}
|
||||
|
||||
В классе CalculatorTest реализованы следующие тесты для метода tg:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{testTg} - тест для проверки тангенса числа типа double. Проверяет положительные, отрицательные значения, а также 0.
|
||||
\end{itemize}
|
||||
|
||||
Код тестов представлен в листинге \ref{lst:TgTest}.
|
||||
|
||||
\begin{lstlisting}[caption={Тесты для метода Tg}, label={lst:TgTest}]
|
||||
@ParameterizedTest
|
||||
@ValueSource(doubles = { 0, Math.PI / 6, Math.PI / 4, -Math.PI / 3, 10 })
|
||||
void testTg(double angle) {
|
||||
double expected = Math.tan(angle);
|
||||
double actual = calculator.tg(angle);
|
||||
assertEquals(expected, actual, 0.0001);
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Результаты запуска тестов:}
|
||||
|
||||
Результаты запуска тестов представлены на рисунке \ref{fig:test4}.
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.65\linewidth]{img/test4.png}
|
||||
\caption{Результаты запуска тестов для метода tg}
|
||||
\label{fig:test4}
|
||||
\end{figure}
|
||||
|
||||
По итогам запуска, метод tg прошел лишь 1 из 5 тестов.
|
||||
|
||||
\subsubsection{Результаты работы №1}
|
||||
В результате комплексного тестирования библиотеки \texttt{calculator.jar} были получены следующие результаты:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Тестирование метода сложения (SumTests)}:
|
||||
\begin{itemize}
|
||||
\item Все тесты корректности сложения для целых чисел и чисел с плавающей точкой прошли успешно
|
||||
\item Операции с граничными значениями (максимальные/минимальные значения \texttt{long} и \texttt{double}) выполняются без переполнения
|
||||
\item Особые случаи (сложение с нулем) соответствуют ожидаемым результатам.
|
||||
\end{itemize}
|
||||
\item \textbf{Тестирование метода умножения (MulTests)}:
|
||||
\begin{itemize}
|
||||
\item Метод для умножения целых чисел прошёл все тесты.
|
||||
\item Метод для умножения чисел с плавающей точкой прошёл 1 из 4 тестов.
|
||||
\end{itemize}
|
||||
|
||||
\item \textbf{Тестирование метода квадратного корня (SqrtTests)}:
|
||||
\begin{itemize}
|
||||
\item Метод прошёл 3 из 4 тестов.
|
||||
\item Метод корректно обрабатывает положительные значения и 0.
|
||||
\item Отрицательные числа обрабатываются некорректно. Вместо того, чтобы вернуть ошибку или \texttt{NaN}, метод вычисляет значения корня по модулю числа.
|
||||
\end{itemize}
|
||||
|
||||
\item \textbf{Тестирование метода тангенса (tgTests)}:
|
||||
\begin{itemize}
|
||||
\item Метод прошёл 1 из 5 тестов.
|
||||
\item Функция тангенса фактически всегда возвращает 1 (кроме случаев, когда \texttt{sin(a) = 0})
|
||||
\item Свойство нечетности (\texttt{tg(-x) = -tg(x)}) не соблюдается, значение \texttt{tg(x)} равно 1.
|
||||
\item Функция возвращает неккоректное значение при попытке вычислить \texttt{tg(0)}. При вычислении возваращется \texttt{NaN}, а не 0, как ожидается.
|
||||
\end{itemize}
|
||||
|
||||
\item \textbf{Общие выводы:}
|
||||
|
||||
Два из четырёх тестируемых методов не прошли все тесты. В реализации методов умножения и вычисления тангенса присутствуют ошибки.
|
||||
|
||||
Метод умножения неккоректно работает с дробными числами. А метод для вычисления тангенса возвращает 1 для любого входного значения, кроме 0. При нулевом входном значении метод возвращает \texttt{NaN}.
|
||||
\end{enumerate}
|
||||
|
||||
\newpage
|
||||
\subsection{Работа №2}
|
||||
В ходе выполнения работы №2 необходимо было реализовать два теста для тестирования web-сайта с помощью библиотеки Selenium WebDriver. Тесты должны проверять, что элементы сайта \texttt{https://jdi-testing.github.io/jdi-light/index.html} отображаются корректно и позволяют взаимодействовать с собой правильным образом. Реализация тестов должна быть выполнена согласно Java Code Convention и запускаться с помощью TestNG suite xml.\par
|
||||
|
||||
Тесты разделяются на 2 класса, в которых необходимо реализовать тесты, связанные с взаимодействием сайта.
|
||||
|
||||
В первом наборе тестов необходимо проверить корректность отображения страницы. Все сценарии, которые необходимо проверить, представлены в \hyperref[tab1]{таблице 1}
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\label{tab1}
|
||||
\caption{\centering{Тест-кейсы для веб-приложения (с использованием SoftAsserts)}}
|
||||
\footnotesize
|
||||
\begin{tabularx}{\textwidth}{|c|>{\centering\arraybackslash}X|>{\centering\arraybackslash}X|>{\centering\arraybackslash}X|}
|
||||
\hline
|
||||
№ & Шаг тестирования & Данные & Ожидаемый результат \\
|
||||
\hline
|
||||
1 & Открыть тестовый сайт по URL & \url{https://jdi-testing.github.io/jdi-light/index.html} & Тестовый сайт открыт \\
|
||||
\hline
|
||||
2 & Проверить заголовок браузера & "Home Page" & Заголовок соответствует "Home Page" \\
|
||||
\hline
|
||||
3 & Выполнить вход в систему & Логин: Roman, Пароль: Jdi1234 & Пользователь авторизован \\
|
||||
\hline
|
||||
4 & Проверить отображение имени пользователя & "ROMAN IOVLEV" & Имя отображается корректно \\
|
||||
\hline
|
||||
5 & Проверить пункты меню в шапке & "HOME", "CONTACT FORM", "SERVICE", "METALS \& COLORS" & 4 пункта меню с правильным текстом \\
|
||||
\hline
|
||||
6 & Проверить изображения на странице & 4 изображения & Все изображения отображаются \\
|
||||
\hline
|
||||
7 & Проверить тексты под иконками & 4 текстовых блока & Тексты соответствуют ожидаемым \\
|
||||
\hline
|
||||
8 & Проверить наличие iframe & Кнопка "Frame Button" & iframe существует \\
|
||||
\hline
|
||||
9 & Проверить кнопку во фрейме & - & Кнопка "Frame Button" доступна \\
|
||||
\hline
|
||||
10 & Вернуться в основное окно & - & Фокус на основном окне \\
|
||||
\hline
|
||||
11 & Проверить левое меню & "Home", "Contact form", "Service", "Metals \& Colors", "Elements packs" & 5 пунктов меню с правильным текстом \\
|
||||
\hline
|
||||
12 & Закрыть браузер & - & Браузер закрыт \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}\par
|
||||
Во втором наборе тестов необходимо проверить корректность взаимодействия пользователя с сайтом (в частности, правильность выбора чекбоксов, радиобаттонов и элементов из выпадающего списка).
|
||||
Таблица тестов, необходимых к реализации во втором упражнении, представлена в \hyperref[tab2]{таблице 2}.
|
||||
|
||||
\begin{table}[h!]
|
||||
\centering
|
||||
\label{tab2}
|
||||
\caption{\centering{Тест-кейсы для веб-приложения (с использованием SoftAsserts)}}
|
||||
\footnotesize
|
||||
\begin{tabularx}{\textwidth}{|c|>{\RaggedRight\arraybackslash}X|>{\RaggedRight\arraybackslash}X|>{\RaggedRight\arraybackslash}X|}
|
||||
\hline
|
||||
\ № & Шаг тестирования (Testing Step) & Данные (Data) & Ожидаемый результат (Expected Result) \\
|
||||
\hline
|
||||
1 & Открыть тестовый сайт по URL & \url{https://jdi-testing.github.io/jdi-light/index.html} & Тестовый сайт открыт (Test site is opened) \\
|
||||
\hline
|
||||
2 & Проверить заголовок браузера (Check browser title) & "Home Page" & Заголовок соответствует "Home Page" (Title matches "Home Page") \\
|
||||
\hline
|
||||
3 & Выполнить вход в систему (Perform login) & username: Roman, password: Jdi1234 & Пользователь авторизован (User is logged in) \\
|
||||
\hline
|
||||
4 & Проверить отображение имени пользователя (Verify username display) & "ROMAN IOVLEV" & Имя отображается корректно (Name is displayed correctly) \\
|
||||
\hline
|
||||
5 & Открыть через хедер меню Service -> Different Elements Page (Navigate using header menu: Service -> Different Elements Page) & & Страница открыта (Page is opened) \\
|
||||
\hline
|
||||
6 & Выбрать чекбоксы (Select checkboxes) & Water, Wind & Элементы отмечены (Elements are checked) \\
|
||||
\hline
|
||||
7 & Выбрать переключатель (Select radio) & Selen & Элемент отмечен (Element is selected) \\
|
||||
\hline
|
||||
8 & Выбрать в один из выпадающего списка (Select in dropdown) & Yellow & Элемент выбран (Element is chosen) \\
|
||||
\hline
|
||||
9 & Проверить, что для каждого чекбокса, radio и dropdown есть отдельная строчка лога (Verify that for each checkbox, radio, and dropdown there is a separate log row) & & Логи отображаются и соответствуют выбранным значениям (Logs are displayed and correspond to selected values) \\
|
||||
\hline
|
||||
10 & Закрыть браузер (Close browser) & & Браузер закрыт (Browser is closed) \\
|
||||
\hline
|
||||
\end{tabularx}
|
||||
\end{table}
|
||||
\subsubsection{Класс DriverSetup}
|
||||
Класс \texttt{DriverSetup} выполняет первоначальную настройку \texttt{WebDriver} перед запуском тестов. Он устанавливает системные свойства для Chrome Driver, настраивает HTTP клиент и создает экземпляр Chrome Driver, открывая тестовый сайт и выполняет авторизацию пользователя.
|
||||
|
||||
\begin{lstlisting}[label= list5, caption=\ ]
|
||||
public class DriverSetup {
|
||||
protected static WebDriver driver;
|
||||
|
||||
@BeforeTest
|
||||
public static void setup() {
|
||||
System.setProperty("webdriver.chrome.driver", "src/test/resources/chromedriver.exe");
|
||||
System.setProperty("webdriver.http.factory", "jdk-http-client");
|
||||
|
||||
driver = new ChromeDriver();
|
||||
|
||||
driver.navigate().to("https://jdi-testing.github.io/jdi-light/index.html");
|
||||
|
||||
driver.findElement(By.cssSelector("html > body > header > div > nav > ul.uui-navigation.navbar-nav.navbar-right > li > a > span")).click();
|
||||
driver.findElement(By.id("name")).sendKeys("Roman");
|
||||
driver.findElement(By.id("password")).sendKeys("Jdi1234");
|
||||
driver.findElement(By.id("login-button")).click();
|
||||
}
|
||||
|
||||
@AfterTest
|
||||
public static void exit() {
|
||||
driver.close();
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Класс содержит следующие элементы:
|
||||
\begin{itemize}
|
||||
\item \textbf{driver}: Защищенная статическая переменная типа WebDriver, представляющая экземпляр браузера Chrome, используемый для выполнения тестов.
|
||||
\item \textbf{@BeforeTest setup()}: Статический метод, помеченный аннотацией @BeforeTest, выполняемый перед всеми тестовыми методами. Он выполняет следующие действия:
|
||||
\begin{itemize}
|
||||
\item Устанавливает системные свойства `webdriver.chrome.driver` и `webdriver.http.factory`.
|
||||
\item Создает экземпляр `ChromeDriver`.
|
||||
\item Открывает тестовый сайт по URL: \url{https://jdi-testing.github.io/jdi-light/index.html}.
|
||||
\item Выполняет вход в систему, находя и заполняя поля логина и пароля, а также нажимая кнопку входа.
|
||||
\end{itemize}
|
||||
\item \textbf{@AfterTest exit()}: Статический метод, помеченный аннотацией `@AfterTest`, выполняемый после всех тестовых методов. Он закрывает браузер с помощью `driver.close()`.
|
||||
\end{itemize}
|
||||
\subsubsection{Класс Task1Test}
|
||||
Класс \texttt{Task1Test} является тестовым классом, который выполняет проверки различных элементов на главной странице веб-сайта. Для проверки ожидаемых результатов используются "мягкие" утверждения (SoftAsserts), что позволяет продолжить выполнение теста даже в случае неудачи одного из утверждений.
|
||||
|
||||
\begin{lstlisting}[language=Java, caption=Класс Task1Test, basicstyle=\footnotesize\ttfamily, breaklines=true]
|
||||
package edu.hsai.homework2;
|
||||
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.asserts.SoftAssert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Task1Test extends DriverSetup {
|
||||
@Test
|
||||
public void testTask1() {
|
||||
SoftAssert softAssert = new SoftAssert();
|
||||
|
||||
softAssert.assertEquals(driver.getTitle(), "Home Page");
|
||||
|
||||
softAssert.assertEquals(driver.findElement(By.id("user-name")).getText(), "ROMAN IOVLEV");
|
||||
|
||||
List<WebElement> headerItems = driver.findElements(By.cssSelector("ul.uui-navigation.nav > li"));
|
||||
softAssert.assertEquals(headerItems.size(), 4);
|
||||
|
||||
String[] expectedHeaderTexts = {"HOME", "CONTACT FORM", "SERVICE", "METALS & COLORS"};
|
||||
for (int i = 0; i < headerItems.size(); i++) {
|
||||
softAssert.assertTrue(headerItems.get(i).isDisplayed());
|
||||
softAssert.assertEquals(headerItems.get(i).getText(), expectedHeaderTexts[i]);
|
||||
}
|
||||
|
||||
List<WebElement> images = driver.findElements(By.cssSelector(".benefit-icon > span"));
|
||||
softAssert.assertEquals(images.size(), 4);
|
||||
for (WebElement image : images) {
|
||||
softAssert.assertTrue(image.isDisplayed());
|
||||
}
|
||||
|
||||
List<WebElement> texts = driver.findElements(By.className("benefit-txt"));
|
||||
softAssert.assertEquals(texts.size(), 4);
|
||||
|
||||
String[] expectedTexts = {
|
||||
"To include good practices\nand ideas from successful\nEPAM project",
|
||||
"To be flexible and\ncustomizable",
|
||||
"To be multiplatform",
|
||||
"Already have good base\n (about 20 internal and \n some external projects), \n wish to get more..."
|
||||
};
|
||||
|
||||
for (int i = 0; i < texts.size(); i++) {
|
||||
softAssert.assertEquals(texts.get(i).getText(), expectedTexts[i]);
|
||||
}
|
||||
|
||||
WebElement iframe = driver.findElement(By.id("frame"));
|
||||
softAssert.assertTrue(iframe.isDisplayed());
|
||||
|
||||
driver.switchTo().frame(iframe);
|
||||
WebElement frameButton = driver.findElement(By.id("frame-button"));
|
||||
softAssert.assertTrue(frameButton.isDisplayed());
|
||||
|
||||
driver.switchTo().defaultContent();
|
||||
|
||||
List<WebElement> leftMenuItems = driver.findElements(By.cssSelector("ul.sidebar-menu.left > li"));
|
||||
softAssert.assertEquals(leftMenuItems.size(), 5);
|
||||
|
||||
String[] expectedMenuTexts = {"Home", "Contact form", "Service", "Metals & Colors", "Elements packs"};
|
||||
for (int i = 0; i < leftMenuItems.size(); i++) {
|
||||
WebElement item = leftMenuItems.get(i);
|
||||
softAssert.assertTrue(item.isDisplayed());
|
||||
softAssert.assertEquals(item.getText(), expectedMenuTexts[i]);
|
||||
}
|
||||
|
||||
softAssert.assertAll();
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Класс содержит следующие основные компоненты:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Наследование от DriverSetup}: Класс \texttt{Task1Test} наследуется от класса \texttt{DriverSetup}, который выполняет предварительную настройку WebDriver и открывает веб-сайт.
|
||||
\item \textbf{@Test testTask1()}: Это тестовый метод, помеченный аннотацией \texttt{@Test}, который указывает, что это метод TestNG для выполнения тестов.
|
||||
\item \textbf{SoftAssert softAssert = new SoftAssert()}: Создание экземпляра \texttt{SoftAssert}, который позволяет собирать ошибки и не останавливать выполнение теста при первой неудаче.
|
||||
\item \textbf{Проверки (Assertions)}: Метод содержит ряд проверок с использованием \texttt{softAssert.assertEquals()} и \texttt{softAssert.assertTrue()} для проверки различных элементов веб-страницы:
|
||||
\begin{itemize}
|
||||
\item Заголовок страницы (\texttt{softAssert.assertEquals(driver.getTitle(), "Home Page")})).
|
||||
\item Имя пользователя (\texttt{softAssert.assertEquals(driver.findElement(By.id("user-name")).getText(), "ROMAN IOVLEV")})).
|
||||
\item Элементы в секции заголовка (количество и текст элементов меню).
|
||||
\item Изображения на главной странице (количество и отображение).
|
||||
\item Тексты под иконками (количество и соответствие ожидаемым текстам).
|
||||
\item Наличие и отображение iframe.
|
||||
\item Наличие и отображение кнопки во iframe.
|
||||
\item Элементы в левом меню (количество и текст элементов).
|
||||
\end{itemize}
|
||||
\item \textbf{Переключение на iframe и обратно}: В коде происходит переключение на iframe для проверки содержимого внутри него, а затем возврат обратно к основному содержанию страницы.
|
||||
\item \textbf{softAssert.assertAll()}: Вызов этого метода в конце тестового метода позволяет убедиться, что все собранные ошибки будут выведены, и тест завершится с соответствующим статусом.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Класс Task2Test}
|
||||
Класс \texttt{Task2Test} является тестовым классом, который проверяет различные элементы и функциональности веб-сайта. Он использует библиотеку Selenium WebDriver для взаимодействия с веб-страницей и библиотеку TestNG для организации и выполнения тестов. Класс выполняет проверку заголовка страницы, имени пользователя, а также взаимодействует с элементами на странице "Different Elements" (чекбоксы, радиокнопки, выпадающий список) и проверяет логи.
|
||||
|
||||
\begin{lstlisting}[language=Java, caption=Класс Task2Test, basicstyle=\footnotesize\ttfamily, breaklines=true]
|
||||
public class Task2Test extends DriverSetup {
|
||||
private static final By USER_NAME = By.id("user-name");
|
||||
|
||||
@Test
|
||||
public void testBrowserTitle() {
|
||||
assertEquals(driver.getTitle(), "Home Page", "Browser title should be 'Home Page'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLogin() {
|
||||
WebElement userNameElement = new WebDriverWait(driver, Duration.ofSeconds(10))
|
||||
.until(ExpectedConditions.visibilityOfElementLocated(USER_NAME));
|
||||
|
||||
assertTrue(userNameElement.isDisplayed(), "Username should be displayed");
|
||||
assertEquals(userNameElement.getText(), "ROMAN IOVLEV", "Username should be 'ROMAN IOVLEV'");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testElements() {
|
||||
WebElement serviceDropdown = driver.findElement(By.cssSelector("header .nav > li.dropdown"));
|
||||
serviceDropdown.click();
|
||||
|
||||
WebElement differentElementsLink = driver.findElement(By.xpath("//a[text()='Different elements']"));
|
||||
differentElementsLink.click();
|
||||
assertEquals(driver.getTitle(), "Different Elements", "Заголовок страницы 'Different Elements' неверный.");
|
||||
|
||||
List<String> checkboxesToSelect = Arrays.asList("Water", "Wind");
|
||||
List<WebElement> checkboxes = new WebDriverWait(driver, Duration.ofSeconds(10))
|
||||
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(
|
||||
By.cssSelector(".label-checkbox")
|
||||
));
|
||||
|
||||
for (WebElement checkbox : checkboxes) {
|
||||
if (checkboxesToSelect.contains(checkbox.getText())) {
|
||||
if (!checkbox.findElement(By.tagName("input")).isSelected()) {
|
||||
checkbox.click();
|
||||
}
|
||||
assertTrue(checkbox.findElement(By.tagName("input")).isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
String radioToSelect = "Selen";
|
||||
List<WebElement> radios = new WebDriverWait(driver, Duration.ofSeconds(10))
|
||||
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(
|
||||
By.cssSelector(".label-radio")
|
||||
));
|
||||
|
||||
for (WebElement radio : radios) {
|
||||
if (radio.getText().equals(radioToSelect)) {
|
||||
radio.click();
|
||||
assertTrue(radio.findElement(By.tagName("input")).isSelected());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String dropdownValueToSelect = "Yellow";
|
||||
WebElement dropdown = new WebDriverWait(driver, Duration.ofSeconds(10))
|
||||
.until(ExpectedConditions.elementToBeClickable(
|
||||
By.cssSelector(".colors select")
|
||||
));
|
||||
|
||||
Select select = new Select(dropdown);
|
||||
select.selectByVisibleText(dropdownValueToSelect);
|
||||
assertEquals(select.getFirstSelectedOption().getText(), dropdownValueToSelect);
|
||||
|
||||
List<WebElement> logs = new WebDriverWait(driver, Duration.ofSeconds(10))
|
||||
.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(
|
||||
By.cssSelector(".logs li")
|
||||
));
|
||||
for (var elem : logs)
|
||||
System.out.println(elem.getText());
|
||||
|
||||
List<String> expectedLogs = Arrays.asList(
|
||||
"Water: condition changed to true",
|
||||
"Wind: condition changed to true",
|
||||
"metal: value changed to Selen",
|
||||
"Colors: value changed to Yellow"
|
||||
);
|
||||
|
||||
for (int i = 0; i < expectedLogs.size(); i++) {
|
||||
String actualLog = logs.get((logs.size()-1) - i).getText().replaceAll("\\d{2}:\\d{2}:\\d{2}", "").trim();
|
||||
assertTrue(actualLog.endsWith(expectedLogs.get(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Класс содержит следующие основные компоненты:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Наследование от DriverSetup}: Класс \texttt{Task2Test} наследуется от класса \texttt{DriverSetup}, который выполняет предварительную настройку WebDriver и открывает веб-сайт.
|
||||
\item \textbf{Поле USER\_NAME}: Приватное статическое поле \texttt{USER\_NAME} типа \texttt{By}, содержащее локатор для элемента с именем пользователя.
|
||||
\item \textbf{@Test testBrowserTitle()}: Тестовый метод, который проверяет заголовок браузера на соответствие значению "Home Page". Использует \texttt{assertEquals} для проверки.
|
||||
\item \textbf{@Test testLogin()}: Тестовый метод, который проверяет, что имя пользователя отображается и соответствует ожидаемому значению "ROMAN IOVLEV". Использует явное ожидание (\texttt{WebDriverWait}) для проверки видимости элемента.
|
||||
\item \textbf{@Test testElements()}: Тестовый метод, который выполняет следующие шаги:
|
||||
\begin{itemize}
|
||||
\item Открывает страницу "Different Elements" через меню "Service".
|
||||
\item Выбирает чекбоксы "Water" и "Wind".
|
||||
\item Выбирает радиокнопку "Selen".
|
||||
\item Выбирает значение "Yellow" в выпадающем списке.
|
||||
\item Проверяет логи на соответствие ожидаемым значениям.
|
||||
\end{itemize}
|
||||
\item \textbf{Явные ожидания (WebDriverWait)}: Используются для ожидания появления и кликабельности элементов, что делает тесты более стабильными.
|
||||
\item \textbf{Проверка логов}: Код проверяет логи на соответствие ожидаемым значениям, учитывая порядок и формат записей.
|
||||
\end{itemize}
|
||||
\subsubsection{Результаты работы №2}
|
||||
Результаты запуска тестов представлены на Рис.~\ref{fig:selenium-tests}
|
||||
|
||||
\begin{figure}[h!]
|
||||
\centering
|
||||
\includegraphics[width=0.35\linewidth]{img/selenium-tests.png}
|
||||
\caption{Результаты выполнения тестов Selenium WebDriver}
|
||||
\label{fig:selenium-tests}
|
||||
\end{figure}
|
||||
|
||||
Все разработанные тесты для проверки веб-сайта успешно пройдены. Тесты охватывают широкий спектр элементов страницы, включая заголовки, элементы навигации, iframe, чекбоксы и выпадающие списки.
|
||||
|
||||
|
||||
|
||||
\newpage
|
||||
\section*{Заключение}
|
||||
\addcontentsline{toc}{section}{Заключение}
|
||||
|
||||
В ходе выполнения лабораторной работы были изучены ключевые аспекты автоматизированного тестирования программного обеспечения. Работа охватила создание, написание и выполнение юнит-тестов для Java-библиотеки calculator.jar с использованием JUnit, а также организацию тестирования веб-страниц с помощью Selenium WebDriver и TestNG.
|
||||
|
||||
В результате тестирования библиотеки calculator.jar были обнаружены неточности в реализации некоторых методов, в частности, неверное вычисление тангенса и некорректная работа с числами с плавающей точкой при умножении. Эти ошибки могли бы остаться незамеченными при поверхностном ручном тестировании, что демонстрирует ценность автоматизированного подхода.
|
||||
|
||||
При тестировании веб-сайта с помощью Selenium WebDriver была подтверждена корректность отображения элементов и их функциональность. Успешное прохождение всех тестов показало, что сайт работает в соответствии с ожиданиями в тестовых сценариях.
|
||||
|
||||
Использованные инструменты автоматизированного тестирования продемонстрировали себя как эффективное средство для систематической проверки программного обеспечения на соответствие требованиям. Они позволяют выполнять тесты на больших наборах данных и многократно повторять одни и те же сценарии, что затруднительно при ручном тестировании.
|
||||
|
||||
Тем не менее, автоматизированное тестирование имеет свои ограничения. Оно фокусируется преимущественно на проверке функциональности и не способно в полной мере оценить удобство использования или обнаружить непредвиденные сценарии использования. Кроме того, сами автоматизированные тесты могут содержать ошибки.
|
||||
|
||||
Таким образом, можно заключить, что наиболее эффективный подход к тестированию сочетает в себе автоматизированные и ручные методы. Автоматизированное тестирование обеспечивает стабильность и повторяемость проверок, а ручное позволяет выявлять проблемы, связанные с удобством использования и нестандартными сценариями. Комплексное применение обоих подходов существенно повышает качество программного обеспечения.
|
||||
|
||||
\newpage
|
||||
\section*{Список литературы}
|
||||
\addcontentsline{toc}{section}{Список литературы}
|
||||
|
||||
\vspace{-1.5cm}
|
||||
\begin{thebibliography}{0}
|
||||
\bibitem{1} {Что такое Selenium WebDriver? — Habr. [Электронный ресурс]. \\URL: \href{https://habr.com/ru/articles/152971/}{https://habr.com/ru/articles/152971/} (дата обращения: 30.04.2025).}
|
||||
|
||||
\bibitem{2} {Selenium IDE — Habr. [Электронный ресурс]. \\URL: \href{https://habr.com/ru/articles/590607/}{https://habr.com/ru/articles/590607/} (дата обращения: 30.04.2025).}
|
||||
\end{thebibliography}
|
||||
|
||||
\end{document}
|
||||
Reference in New Issue
Block a user